using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Media;
using Avalonia.Threading;
using ReactiveUI;
using ReactiveUI.Validation.Helpers;
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using VeloeMinecraftLauncher.Utils.Starter;
using VeloeMinecraftLauncher.Views;
using VeloeMinecraftLauncher.Views.TitleBar;

namespace VeloeMinecraftLauncher.ViewModels;

public class ViewModelBase : ReactiveValidationObject
{
    protected Serilog.ILogger _logger;

    public ViewModelBase(Serilog.ILogger logger)
    {
        _logger = logger;
    }

    public ViewModelBase()
    {
        this.RaisePropertyChanged(nameof(InterfaceColor));
        this.RaisePropertyChanged(nameof(MaterialOpacity));

    }
    public Color InterfaceColor
    {
        get => Color.Parse("Black");
        set => this.RaisePropertyChanged(nameof(InterfaceColor));
    }

    public float MaterialOpacity
    {
        get => 0.5F;
        set => this.RaisePropertyChanged(nameof(MaterialOpacity));
    }

    public void OpenErrorWindow(Exception ex)
    {
        string message = string.Empty;
        string stackTrace = string.Empty;
        string logfile = string.Empty;
        Exception? innerException;
        switch (ex)
        {
            case WebException or Win32Exception or JavaProcessException or IOException:
                message = ex.Message;
                _logger.Error(ex.Message);

                if (ex is JavaProcessException javaEx && Path.Exists(javaEx.LogPath))
                        logfile = ((JavaProcessException)ex).LogPath;                   

                if (ex.StackTrace is not null)
                    _logger.Error(ex.StackTrace);
                innerException = ex.InnerException;
                while (innerException is not null)
                {
                    _logger.Error(innerException.Message);
                    if (innerException.StackTrace is not null)
                        _logger.Error(innerException.StackTrace);
                    innerException = innerException.InnerException;
                }
                break;
            default:
                message = ex.Message;
                stackTrace = ex.StackTrace ?? string.Empty;
                _logger.Error(ex.Message);
                if (ex.StackTrace is not null)
                    _logger.Error(ex.StackTrace);
                innerException = ex.InnerException;
                while (innerException is not null)
                {
                    message += "\n" + innerException.Message;
                    stackTrace += "\n" + innerException.StackTrace;
                    _logger.Error(innerException.Message);
                    if (innerException.StackTrace is not null)
                        _logger.Error(innerException.StackTrace);
                    innerException = innerException.InnerException;
                }
                break;
        }       

        OpenErrorWindow(message, logfile, stackTrace);
    }

    public static void OpenErrorWindow(string message, string logfile = "", string stackTrace = "")
    {       
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
        if (Application.Current is not null && Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            Dispatcher.UIThread.InvokeAsync(() =>
            {
                var ErrorMessageViewModel = new MessageWindowViewModel(message, "Error message", logfile: logfile);
                var ErrorMessage = new MessageWindow()
                {
                    WindowStartupLocation = WindowStartupLocation.CenterOwner,
                    DataContext = ErrorMessageViewModel
                };
                //TODO change it to binding
                ErrorMessage.GetControl<TitleBarWindow>("titleBar").TitleText = "Error Message";
                    
                ErrorMessage.ShowDialog(desktop.MainWindow);
            });
        }     
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
    }
}

