using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.IO;
using Barotrauma;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using System.Xml;
using System.Xml.Linq;
using HarmonyLib;
namespace QICrabUI
{
  public partial class CUIComponent
  {
    /// 
    /// Just a wrapper for CUIProps
    /// idk how to separate them better
    /// 
    //TODO this should be a dict, and cuiprop should have hash
    public CUIComponentProps CUIProps { get; set; } = new();
    public class CUIComponentProps
    {
      public CUIProp ZIndex = new CUIProp()
      {
        LayoutProp = true,
        OnSet = (v, host) =>
          {
            foreach (var child in host.Children)
            {
              //HACK think, should i propagate null?
              if (v.HasValue && !child.IgnoreParentZIndex)
              {
                child.ZIndex = v.Value + 1;
              }
            }
          },
      };
      public CUIProp IgnoreEvents = new CUIProp()
      {
        OnSet = (v, host) =>
          {
            foreach (var child in host.Children)
            {
              if (!child.IgnoreParentEventIgnorance) child.IgnoreEvents = v;
            }
          },
      };
      public CUIProp Visible = new CUIProp()
      {
        Value = true,
        OnSet = (v, host) =>
        {
          foreach (var child in host.Children)
          {
            if (!child.IgnoreParentVisibility) child.Visible = v;
          }
        },
      };
      public CUIProp Revealed = new CUIProp()
      {
        Value = true,
        OnSet = (v, host) =>
        {
          // host.TreeChanged = true;
          host.Visible = v;
          host.IgnoreEvents = !v;
        },
      };
      public CUIProp Ghost = new CUIProp()
      {
        LayoutProp = true,
        AbsoluteProp = true,
      };
      public CUIProp CullChildren = new CUIProp()
      {
        OnSet = (v, host) =>
        {
          host.HideChildrenOutsideFrame = v;
        },
      };
      public CUIProp ChildrenOffset = new CUIProp()
      {
        ChildProp = true,
        Value = new CUI3DOffset(0, 0, 1), // uuuuuuuuu suka blyat!
        Validate = (v, host) => host.ChildOffsetBounds.Check(v),
        OnSet = (v, host) =>
        {
          foreach (var child in host.Children)
          {
            if (!child.Fixed) child.Scale = v.Z;
          }
        },
      };
      public CUIProp ResizeToSprite = new CUIProp()
      {
        LayoutProp = true,
        OnSet = (v, host) =>
        {
          if (v)
          {
            host.Absolute = host.Absolute with
            {
              Width = host.BackgroundSprite.SourceRect.Width,
              Height = host.BackgroundSprite.SourceRect.Height,
            };
          }
        },
      };
      public CUIProp FillEmptySpace = new CUIProp()
      {
        LayoutProp = true,
      };
      public CUIProp FitContent = new CUIProp()
      {
        LayoutProp = true,
        AbsoluteProp = true,
      };
      public CUIProp Absolute = new CUIProp()
      {
        LayoutProp = true,
        AbsoluteProp = true,
      };
      public CUIProp AbsoluteMin = new CUIProp()
      {
        LayoutProp = true,
        AbsoluteProp = true,
      };
      public CUIProp AbsoluteMax = new CUIProp()
      {
        LayoutProp = true,
        AbsoluteProp = true,
      };
      public CUIProp Relative = new CUIProp()
      {
        LayoutProp = true,
      };
      public CUIProp RelativeMin = new CUIProp()
      {
        LayoutProp = true,
      };
      public CUIProp RelativeMax = new CUIProp()
      {
        LayoutProp = true,
      };
      public CUIProp CrossRelative = new CUIProp()
      {
        LayoutProp = true,
      };
      #region Graphic Props --------------------------------------------------------
      #endregion
      public CUIProp Palette = new CUIProp()
      {
        ShowInDebug = false,
        OnSet = (v, host) =>
        {
          //TODO should this be called in deserialize?
          CUIGlobalStyleResolver.OnComponentStyleChanged(host);
          // foreach (var child in host.Children)
          // {
          //   child.Palette = v;
          // }
        },
      };
      public CUIProp BackgroundSprite = new CUIProp()
      {
        Value = CUISprite.Default,
        ShowInDebug = false,
        Validate = (v, host) => v ?? CUISprite.Default,
        OnSet = (v, host) =>
        {
          if (host.ResizeToSprite)
          {
            host.Absolute = host.Absolute with
            {
              Width = v.SourceRect.Width,
              Height = v.SourceRect.Height,
            };
          }
          if (host.IgnoreTransparent)
          {
            Rectangle bounds = host.BackgroundSprite.Texture.Bounds;
            host.TextureData = new Color[bounds.Width * bounds.Height];
            host.BackgroundSprite.Texture.GetData(host.TextureData);
          }
        },
      };
      public CUIProp IgnoreTransparent = new CUIProp()
      {
        OnSet = (v, host) =>
        {
          if (v)
          {
            Rectangle bounds = host.BackgroundSprite.Texture.Bounds;
            host.TextureData = new Color[bounds.Width * bounds.Height];
            host.BackgroundSprite.Texture.GetData(host.TextureData);
          }
          else
          {
            host.TextureData = null;
          }
        },
      };
      public CUIProp BackgroundColor = new CUIProp()
      {
        ShowInDebug = false,
        OnSet = (v, host) =>
        {
          host.BackgroundVisible = v != Color.Transparent;
        },
      };
      public CUIProp OutlineColor = new CUIProp()
      {
        ShowInDebug = false,
        OnSet = (v, host) =>
        {
          host.OutlineVisible = v != Color.Transparent;
        },
      };
      public CUIProp Padding = new CUIProp()
      {
        Value = new Vector2(2, 2),
        DecorProp = true,
      };
    }
  }
}