using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using InABox.Core;
using InABox.Wpf;
using InABox.WPF;
using Syncfusion.Windows.Shared;
using Xceed.Wpf.AvalonDock.Themes;

namespace InABox.DynamicGrid
{

    /// <summary>
    ///     Interaction logic for DynamicExportForm.xaml
    /// </summary>
    public partial class DynamicExportForm : ThemableWindow
    {
        private readonly Type _entitytype;

        public DynamicExportForm(Type entitytype, IEnumerable<string> Selected)
        {
            InitializeComponent();

            Fields = Array.Empty<string>();
            ChildMappings = new();

            var codeProperty = EntityCode(entitytype);
            if (codeProperty != null)
            {
                var m2mTypes = DynamicGridUtils.GetManyToManyTypes(entitytype)
                    .Where(x => x.GetInterfaces().Contains(typeof(IExportable)));
                var o2mTypes = DynamicGridUtils.GetOneToManyTypes(entitytype)
                    .Where(x => x.GetInterfaces().Contains(typeof(IExportable)));

                foreach(var type in m2mTypes)
                {
                    var otherType = CoreUtils.GetManyToManyOtherType(type, entitytype);

                    var result = new Inflector.Inflector(new CultureInfo("en")).Pluralize(otherType.Name);

                    AddOtherTab(type, result);
                }

                foreach(var type in o2mTypes)
                {
                    var caption = type.GetCustomAttribute(typeof(Caption));
                    var result = caption != null ? 
                        ((Caption)caption).Text : 
                        new Inflector.Inflector(new CultureInfo("en")).Pluralize(type.Name);

                    AddOtherTab(type, result);
                }
            }

            _entitytype = entitytype;

            ShowHelpImage.Source = Wpf.Resources.help.AsBitmapImage();

            var mappings = ImportFactory.ExtractMappings(_entitytype, ImportMappingType.Export);
            Mappings.HideBlank = true;
            Mappings.Items.AddRange(mappings);
            Mappings.Selected.AddRange(mappings.Where(x => x.Key || Selected.Contains(x.Property)));
            Mappings.Refresh(true, true);
        }

        private DynamicExportMappingGrid CreateOtherTab(Type tabType)
        {
            var mappingsGrid = new DynamicExportMappingGrid();
            var mappings = ImportFactory.ExtractMappings(tabType, ImportMappingType.Export);
            mappingsGrid.HideBlank = true;
            mappingsGrid.Items.AddRange(mappings);
            mappingsGrid.Selected.Clear();
            mappingsGrid.Refresh(true, true);

            return mappingsGrid;
        }

        private void AddOtherTab(Type tabType, string caption)
        {
            var tab = new TabItem() { Header = caption };

            var grid = CreateOtherTab(tabType);
            ChildMappings[tabType] = grid;
            tab.Content = grid;

            TabControl.Items.Add(tab);
        }

        private DynamicExportMappingGrid CurrentMappings
        {
            get => (TabControl.SelectedContent as DynamicExportMappingGrid)!;
        }

        public string[] Fields { get; private set; }

        private Dictionary<Type, DynamicExportMappingGrid> ChildMappings;

        private void ClearAll_Click(object sender, RoutedEventArgs e)
        {
            CurrentMappings.ClearAll();
        }

        private void SelectAll_Click(object sender, RoutedEventArgs e)
        {
            CurrentMappings.SelectAll();
        }

        private void HideBlank_Click(object sender, RoutedEventArgs e)
        {
            CurrentMappings.HideBlank = !CurrentMappings.HideBlank;
            HideBlank.Content = CurrentMappings.HideBlank ? "Show All" : "Hide Blank";
            CurrentMappings.Refresh(false, true);
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
        }

        private void OK_Click(object sender, RoutedEventArgs e)
        {
            Fields = Mappings.Selected.Select(x => x.Property).ToArray();
            DialogResult = true;
        }

        private void ShowHelp_Click(object sender, RoutedEventArgs e)
        {
            Process.Start(new ProcessStartInfo("https://prsdigital.com.au/wiki/index.php/Export_Data") { UseShellExecute = true });
        }

        private IProperty? EntityCode(Type entityType)
        {
            foreach(var property in DatabaseSchema.Properties(entityType))
            {
                var editor = property.Editor;
                if(editor is UniqueCodeEditor)
                {
                    return property;
                }
            }
            return null;
        }

        public Dictionary<Type, IEnumerable<string>> GetChildFields()
        {
            return ChildMappings.ToDictionary(
                x => x.Key,
                x => x.Value.Selected.Select(x => x.Property));
        }
    }
}