using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using InABox.Core;
using Microsoft.Win32;

namespace InABox.DynamicGrid
{
    public enum DocumentAction
    {
        Replace,
        UseExisting,
        MakeCopy
    }

    public class DocumentEditorControl : DynamicEditorControl<Guid>
    {
        public delegate Document? FindDocumentEvent(string FileName);

        public delegate Document? GetDocumentEvent(Guid id);

        public delegate void OnUpdateOtherEditorHandler(string columnname, object value);

        public delegate void SaveDocumentEvent(Document document);

        private Document _document = new();

        private TextBox Editor;

        public DocumentEditorControl()
        {
            OtherColumns = new Dictionary<string, string>();
        }

        public Dictionary<string, string> OtherColumns { get; }

        public string Filter { get; set; }
        public event GetDocumentEvent? OnGetDocument;
        public event FindDocumentEvent? OnFindDocument;
        public event SaveDocumentEvent? OnSaveDocument;
        public event OnUpdateOtherEditorHandler? OnUpdateOtherEditor;

        protected override FrameworkElement CreateEditor()
        {
            var Grid = new Grid
            {
                VerticalAlignment = VerticalAlignment.Stretch,
                HorizontalAlignment = HorizontalAlignment.Stretch
            };
            //Grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(25, GridUnitType.Pixel) });
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50, GridUnitType.Pixel) });
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50, GridUnitType.Pixel) });
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50, GridUnitType.Pixel) });

            Editor = new TextBox
            {
                VerticalAlignment = VerticalAlignment.Stretch,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                Margin = new Thickness(0, 0, 0, 0),
                IsEnabled = false
            };
            //Editor.LostFocus += (o, e) => CheckChanged();
            Editor.SetValue(Grid.ColumnProperty, 0);
            Editor.SetValue(Grid.RowProperty, 0);
            Grid.Children.Add(Editor);

            var Select = new Button
            {
                VerticalAlignment = VerticalAlignment.Stretch,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                Margin = new Thickness(5, 1, 0, 1),
                Content = "Select",
                Focusable = false
            };
            Select.SetValue(Grid.ColumnProperty, 1);
            Select.SetValue(Grid.RowProperty, 0);
            Select.Click += Select_Click;
            Grid.Children.Add(Select);

            var Clear = new Button
            {
                VerticalAlignment = VerticalAlignment.Stretch,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                Margin = new Thickness(5, 1, 0, 1),
                Content = "Clear",
                Focusable = false
            };
            Clear.SetValue(Grid.ColumnProperty, 2);
            Clear.SetValue(Grid.RowProperty, 0);
            Clear.Click += Clear_Click;
            Grid.Children.Add(Clear);

            var View = new Button
            {
                VerticalAlignment = VerticalAlignment.Stretch,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                Margin = new Thickness(5, 1, 0, 1),
                Content = "View",
                Focusable = false
            };
            View.SetValue(Grid.ColumnProperty, 3);
            View.SetValue(Grid.RowProperty, 0);
            View.Click += View_Click;
            Grid.Children.Add(View);

            return Grid;
        }

        private void Select_Click(object sender, RoutedEventArgs e)
        {
            var dlg = new OpenFileDialog();
            dlg.Filter = Filter;
            if (dlg.ShowDialog() == true)
            {
                var filename = Path.GetFileName(dlg.FileName).ToLower();
                var timestamp = new FileInfo(dlg.FileName).LastWriteTime;
                var data = File.ReadAllBytes(dlg.FileName);
                var crc = CoreUtils.CalculateCRC(data);

                //var existing = OnFindDocument?.Invoke(filename);
                //if (existing != null)
                //{
                //    if ((existing.TimeStamp == DateTime.MinValue || existing.TimeStamp.ToString("yyyy-MM-ddThh:mm.ss.fff")
                //            .Equals(timestamp.ToString("yyyy-MM-ddThh:mm.ss.fff"))) && existing.CRC.Equals(crc))
                //    {
                //        if (existing.TimeStamp == DateTime.MinValue)
                //        {
                //            existing.TimeStamp = timestamp;
                //            OnSaveDocument?.Invoke(existing);
                //        }

                //        _document = existing;
                //    }
                //    else
                //    {
                //        var confirm = new DocumentConfirm
                //        {
                //            FileName = filename,
                //            LocalSize = data.Length,
                //            RemoteSize = existing.Data.Length,
                //            LocalTimeStamp = timestamp,
                //            RemoteTimeStamp = existing.TimeStamp
                //        };
                //        if (confirm.ShowDialog() == true)
                //        {
                //            if (confirm.Result == DocumentAction.Replace)
                //            {
                //                existing.Data = data;
                //                existing.TimeStamp = timestamp;
                //                existing.CRC = crc;
                //                OnSaveDocument?.Invoke(existing);
                //                _document = existing;
                //            }
                //            else if (confirm.Result == DocumentAction.UseExisting)
                //            {
                //                _document = existing;
                //            }
                //            else if (confirm.Result == DocumentAction.MakeCopy)
                //            {
                //                var basefilename = Path.GetFileNameWithoutExtension(filename);
                //                var ext = Path.GetExtension(filename);
                //                var i = 0;
                //                while (existing is not null)
                //                {
                //                    i++;
                //                    filename = Path.ChangeExtension(string.Format("{0} ({1})", basefilename, i), ext);
                //                    existing = OnFindDocument?.Invoke(filename);
                //                }

                //                var document = new Document
                //                {
                //                    FileName = filename,
                //                    Data = data,
                //                    TimeStamp = timestamp,
                //                    CRC = crc
                //                };
                //                OnSaveDocument?.Invoke(document);
                //                _document = document;
                //            }
                //        }
                //    }
                //}
                //else
                //{
                //    _document = new Document
                //    {
                //        FileName = filename,
                //        Data = data,
                //        TimeStamp = timestamp,
                //        CRC = crc
                //    };
                //    OnSaveDocument?.Invoke(_document);
                //}

                var newDocument = DocumentConfirm.CheckDocument(new Document
                {
                    FileName = filename,
                    TimeStamp = timestamp,
                    Data = data,
                    CRC = crc
                }, OnFindDocument, out var shouldSave);
                if(newDocument != null)
                {
                    _document = newDocument;
                    if (shouldSave)
                    {
                        OnSaveDocument?.Invoke(newDocument);
                    }
                }

                Editor.Text = _document.FileName;
                if (OtherColumns.ContainsKey("FileName"))
                    OtherValues[OtherColumns["FileName"]] = _document.FileName;
                CheckChanged();
            }
        }

        private void View_Click(object sender, RoutedEventArgs e)
        {
            if (_document.ID == Guid.Empty)
            {
                MessageBox.Show("Please select a document first!");
                return;
            }

            var ext = Path.GetExtension(_document.FileName);
            var filename = Path.ChangeExtension(Path.GetTempFileName(), ext);
            File.WriteAllBytes(filename, _document.Data);

            var gsProcessInfo = new ProcessStartInfo();
            gsProcessInfo.Verb = "open";
            gsProcessInfo.WindowStyle = ProcessWindowStyle.Normal;
            gsProcessInfo.FileName = filename;
            gsProcessInfo.UseShellExecute = true;
            Process.Start(gsProcessInfo);
        }

        private void Clear_Click(object sender, RoutedEventArgs e)
        {
            _document = new Document();
            Editor.Text = "";
            CheckChanged();
        }

        public override int DesiredHeight()
        {
            return 25;
        }

        public override int DesiredWidth()
        {
            return int.MaxValue;
        }

        protected override Guid RetrieveValue()
        {
            return _document.ID;
        }

        protected override void UpdateValue(Guid value)
        {
            if (value != Guid.Empty)
                _document = OnGetDocument?.Invoke(value) ?? new Document();
            Editor.Text = _document.FileName;
        }

        public override void SetFocus()
        {
            Editor.Focus();
        }

        public override void SetColor(Color color)
        {
            Editor.Background = new SolidColorBrush(color);
        }
    }
}