using System;
using InABox.Core;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace InABox.DynamicGrid;


public abstract class DynamicEditorControl<T, TEditor> : BaseDynamicEditorControl<TEditor>, IDynamicEditorControl<T>
    where TEditor : IBaseEditor
{
    //{
    //    get { return (EditorControlValueChangedHandler)GetValue(OnEditorValueChangedProperty); }
    //    set { SetValue(OnEditorValueChangedProperty, value) }
    //}

    protected bool Updating;

    public DynamicEditorControl()
    {
        Loaded = false;
        OtherValues = new();
        MinHeight = 25;
        Focusable = false;
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override bool Changed { get; set; }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public T Value
    {
        get => RetrieveValue();
        set => UpdateValue(value);
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    protected virtual Dictionary<string, object?> OtherValues { get; }

    //public static readonly DependencyProperty OnEditorValueChangedProperty =
    //    DependencyProperty.Register(nameof(OnEditorValueChanged), typeof(EditorControlValueChangedHandler), typeof(DynamicEditorControl<T>));

    public override event EditorControlValueChangedHandler? OnEditorValueChanged;

    protected void EditorValueChanged(IDynamicEditorControl sender, Dictionary<string, object?> values) => OnEditorValueChanged?.Invoke(sender, values);

    protected virtual bool CheckChanged()
    {
        //Logger.Send(LogType.Information, "", string.Format("{0}({1}).CheckChanged()", GetType().EntityName().Split('.').Last(), ColumnName));
        if (Loaded && !Updating)
        {
            Updating = true;
            try
            {
                var values = new Dictionary<string, object?>();

                var sColumn = string.IsNullOrEmpty(ColumnName) ? "" : ColumnName;

                var dotIdx = sColumn.LastIndexOf('.');
                var prefix = "";
                if (dotIdx != -1)
                {
                    prefix = sColumn[..dotIdx];
                }

                values[sColumn] = RetrieveValue();
                foreach (var key in OtherValues.Keys)
                    values[$"{prefix}.{key}"] = OtherValues[key];
                OnEditorValueChanged?.Invoke(this, values);
            }
            finally
            {
                Changed = true;
                Updating = false;
            }
            UpdateInformation();
        }

        return Changed;
    }

    public override void SetValue(string property, object? value)
    {
        UpdateValue(value != null ? (T)value : default);
        base.SetValue(property,value);
    }

    public override object? GetValue(string property)
    {
        return RetrieveValue();
    }

    public override Dictionary<string, object?> GetValues()
    {
        return new Dictionary<string, object?>
        {
            { ColumnName, RetrieveValue() }
        };
    }

    protected abstract T RetrieveValue();
    protected abstract void UpdateValue(T value);

    public override bool ShouldSerializeContent()
    {
        return false;
    }

    public override void SetEnabled(bool enabled)
    {
        if (Content is FrameworkElement element) element.IsEnabled = enabled;
        SetColor(enabled ? Color : Colors.WhiteSmoke);
    }

    public override void SetVisible(bool visible)
    {
        Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
    }
}