using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Terminal.Gui;

namespace UICatalog.Scenarios;

[ScenarioMetadata ("Configuration Editor", "Edits Terminal.Gui Config Files.")]
[ScenarioCategory ("TabView")]
[ScenarioCategory ("Colors")]
[ScenarioCategory ("Files and IO")]
[ScenarioCategory ("TextView")]
public class ConfigurationEditor : Scenario
{
    private static ColorScheme _editorColorScheme = new ()
    {
        Normal = new Attribute (Color.Red, Color.White),
        Focus = new Attribute (Color.Red, Color.Black),
        HotFocus = new Attribute (Color.BrightRed, Color.Black),
        HotNormal = new Attribute (Color.Magenta, Color.White)
    };

    private static Action _editorColorSchemeChanged;
    private Shortcut _lenShortcut;
    private TileView _tileView;

    [SerializableConfigurationProperty (Scope = typeof (AppScope))]
    public static ColorScheme EditorColorScheme
    {
        get => _editorColorScheme;
        set
        {
            _editorColorScheme = value;
            _editorColorSchemeChanged?.Invoke ();
        }
    }

    public override void Main ()
    {
        Application.Init ();

        Toplevel top = new ();

        _tileView = new TileView (0)
        {
            Width = Dim.Fill (), Height = Dim.Fill (1), Orientation = Orientation.Vertical, LineStyle = LineStyle.Single
        };

        top.Add (_tileView);

        _lenShortcut = new Shortcut ()
        {
            Title = "Len: ",
        };

        var quitShortcut = new Shortcut ()
        {
            Key = Application.QuitKey,
            Title = $"{Application.QuitKey} Quit",
            Action = Quit
        };

        var reloadShortcut = new Shortcut ()
        {
            Key = Key.F5.WithShift,
            Title = "Reload",
        };
        reloadShortcut.Accept += (s, e) => { Reload (); };

        var saveShortcut = new Shortcut ()
        {
            Key = Key.F4,
            Title = "Save",
            Action = Save
        };

        var statusBar = new StatusBar ([quitShortcut, reloadShortcut, saveShortcut, _lenShortcut]);

        top.Add (statusBar);

        top.Loaded += (s, a) => Open ();

        _editorColorSchemeChanged += () =>
                                     {
                                         foreach (Tile t in _tileView.Tiles)
                                         {
                                             t.ContentView.ColorScheme = EditorColorScheme;
                                             t.ContentView.SetNeedsDisplay ();
                                         }

                                         ;
                                     };

        _editorColorSchemeChanged.Invoke ();

        Application.Run (top);
        top.Dispose ();

        Application.Shutdown ();
    }
    public void Save ()
    {
        if (_tileView.MostFocused is ConfigTextView editor)
        {
            editor.Save ();
        }
    }

    private void Open ()
    {
        var subMenu = new MenuBarItem { Title = "_View" };

        foreach (string configFile in ConfigurationManager.Settings.Sources)
        {
            var homeDir = $"{Environment.GetFolderPath (Environment.SpecialFolder.UserProfile)}";
            var fileInfo = new FileInfo (configFile.Replace ("~", homeDir));

            Tile tile = _tileView.InsertTile (_tileView.Tiles.Count);
            tile.Title = configFile.StartsWith ("resource://") ? fileInfo.Name : configFile;

            var textView = new ConfigTextView
            {
                X = 0,
                Y = 0,
                Width = Dim.Fill (),
                Height = Dim.Fill (),
                FileInfo = fileInfo,
                Tile = tile
            };

            tile.ContentView.Add (textView);

            textView.Read ();

            textView.Enter += (s, e) => { _lenShortcut.Title = $"Len:{textView.Text.Length}"; };
        }

        Application.Top.LayoutSubviews ();
    }

    private void Quit ()
    {
        foreach (Tile tile in _tileView.Tiles)
        {
            var editor = tile.ContentView.Subviews [0] as ConfigTextView;

            if (editor.IsDirty)
            {
                int result = MessageBox.Query (
                                               "Save Changes",
                                               $"Save changes to {editor.FileInfo.FullName}",
                                               "Yes",
                                               "No",
                                               "Cancel"
                                              );

                if (result == -1 || result == 2)
                {
                    // user cancelled
                }

                if (result == 0)
                {
                    editor.Save ();
                }
            }
        }

        Application.RequestStop ();
    }

    private void Reload ()
    {
        if (_tileView.MostFocused is ConfigTextView editor)
        {
            editor.Read ();
        }
    }

    private class ConfigTextView : TextView
    {
        internal ConfigTextView ()
        {
            ContentsChanged += (s, obj) =>
                               {
                                   if (IsDirty)
                                   {
                                       if (!Tile.Title.EndsWith ('*'))
                                       {
                                           Tile.Title += '*';
                                       }
                                       else
                                       {
                                           Tile.Title = Tile.Title.TrimEnd ('*');
                                       }
                                   }
                               };
        }

        internal FileInfo FileInfo { get; set; }
        internal Tile Tile { get; set; }

        internal void Read ()
        {
            Assembly assembly = null;

            if (FileInfo.FullName.Contains ("[Terminal.Gui]"))
            {
                // Library resources
                assembly = typeof (ConfigurationManager).Assembly;
            }
            else if (FileInfo.FullName.Contains ("[UICatalog]"))
            {
                assembly = Assembly.GetEntryAssembly ();
            }

            if (assembly != null)
            {
                string name = assembly
                              .GetManifestResourceNames ()
                              .FirstOrDefault (x => x.EndsWith ("config.json"));
                using Stream stream = assembly.GetManifestResourceStream (name);
                using var reader = new StreamReader (stream);
                Text = reader.ReadToEnd ();
                ReadOnly = true;
                Enabled = true;

                return;
            }

            if (!FileInfo.Exists)
            {
                // Create empty config file
                Text = ConfigurationManager.GetEmptyJson ();
            }
            else
            {
                Text = File.ReadAllText (FileInfo.FullName);
            }

            Tile.Title = Tile.Title.TrimEnd ('*');
        }

        internal void Save ()
        {
            if (!Directory.Exists (FileInfo.DirectoryName))
            {
                // Create dir
                Directory.CreateDirectory (FileInfo.DirectoryName!);
            }

            using StreamWriter writer = File.CreateText (FileInfo.FullName);
            writer.Write (Text);
            writer.Close ();
            Tile.Title = Tile.Title.TrimEnd ('*');
            IsDirty = false;
        }
    }
}
