
using Godot;
using System.Collections.Generic;


namespace Rokojori
{ 

  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/UIInputIcon.svg")]
  public partial class UIInputInfo: UIRegion
  { 
    InputIcon[] _inputIcons = [];
    
    [Export]
    public InputIcon[] inputIcons
    {
      get => _inputIcons;
      set 
      {
        _inputIcons = value;
        // UpdateInfo();
      }
    }

    [Export]
    public LocalizedString locale;

    [Export]
    public bool upperCase;

    [Export]
    public bool updateInfo 
    {
      get => false;
      set { if ( value ){ UpdateInfo(); }}
    }

    [Export]
    public DeviceFilter deviceFilter;

    public override void _Ready()
    {
      UpdateInfo();
    }

    void UpdateInfo()
    {
      Nodes.RemoveAndDeleteChildren( this );

      if ( inputIcons == null )
      {
        return;
      }

      var iiLib = GetInputIconsLibrary();

      if ( iiLib == null )
      {
        // this.LogInfo( "No Input lib!" );
        return;
      }

      var icons = iiLib.ResolveIcons( inputIcons );

      this.LogInfo( "Resolved Icons:\n", inputIcons, "\n>>\n", icons );

      if ( deviceFilter != null )
      {
        var iconsBefore = Lists.From( icons );
        icons = Lists.Filter( icons, i => deviceFilter.BelongsToDevice( i ) );
        this.LogInfo( "Device Filtered Icons:\n", iconsBefore, "\n>>\n", icons );
      }

      icons = iiLib.ResolveIcons( icons.ToArray() );

      icons.ForEach( i => AddIcon( i ) );

      

      if ( locale != null )
      {
        var localeText = this.CreateChild<UIText>( "Locale" );
        localeText.locale = locale;

        localeText.font = iiLib.font;
        localeText.fontSize = this.fontSize != null ? this.fontSize : iiLib.fontSize;

        localeText.Uppercase = upperCase;
        localeText.marginLeft = UINumber.EM( 0.25f );
      }
      
    }


    UI ui;

    public void SetUI( UI ui )
    {
      this.ui = ui;
    }

    InputIconsLibrary GetInputIconsLibrary()
    {
      var ui = this.ui != null ? this.ui : Unique<UI>.Get();

      if ( ui == null )
      {
        ui = this.FindParentThatIs<UI>();

        if ( ui == null )
        {
          this.LogInfo( "No UI in parents >", ui );

          return null;
        }
      }
            
      var lib = ui.settings.inputIconsLibrary;

      return lib;
    }

    void AddIcon( InputIcon inputIcon )
    {
      if ( inputIcon == null )
      {
        return;
      }       
      
      var lib = GetInputIconsLibrary();

      var id = lib.GetInputIconDefinition( inputIcon );

      if ( id == null )
      {
        // this.LogInfo( "No definition found >> ", inputIcon );
        return;
      }

      // this.LogInfo( "Definition found >> ", inputIcon );

      var iconRegion = this.CreateChild<UIRegion>();
      var elements = id.GetIconElementsForIcon( inputIcon );

      elements.ForEach( e => AddElement( iconRegion, e, e == elements[ 0 ] ) );
      
    }

    void AddElement( UIRegion iconRegion, IconElement element, bool isBG )
    {
      var lib = GetInputIconsLibrary();

      if ( element is TextureIconElement textureIconElement )
      {        
        var uiImage = iconRegion.CreateChild<UIImage>();
        uiImage.Texture = textureIconElement.texture;
        uiImage.ExpandMode = TextureRect.ExpandModeEnum.IgnoreSize;
        uiImage.StretchMode = TextureRect.StretchModeEnum.Scale;

        uiImage.height = UINumber.EM( lib.iconHeightInEm );

        if ( isBG )
        {
          uiImage.width  = UINumber.EM( lib.iconHeightInEm * textureIconElement.widthScale );

          if ( textureIconElement.hasBorders )
          {
            var ninePatchType = new NinePatchUIImageType();
            
            ninePatchType.leftPixelOffset   = textureIconElement.borderLeft;
            ninePatchType.rightPixelOffset  = textureIconElement.borderRight;
            ninePatchType.topPixelOffset    = textureIconElement.borderTop;
            ninePatchType.bottomPixelOffset = textureIconElement.borderBottom;

            uiImage.imageType = ninePatchType;          
          }
        }
        else
        {
          var size = textureIconElement.texture.GetSize();
          var ratio = size.X / size.Y;

          uiImage.width    = UINumber.EM( lib.iconHeightInEm ).GetMultiplied( ratio );
          uiImage.top      = UINumber.EM( 0f );
          uiImage.position = UIPosition.Parent_Anchor;

          if ( TextureIconOverlayAlignment.Left == textureIconElement.alignment )
          {
            uiImage.left = UINumber.EM( 0f );
          }

          if ( TextureIconOverlayAlignment.Right == textureIconElement.alignment )
          {
            uiImage.right = UINumber.EM( 0f );
          }
        }

        if ( textureIconElement.rotation != 0 )
        {
          uiImage.rotation = UINumber.Create( textureIconElement.rotation );
        }
      }
      else if ( element is LabelIconElement labelIconElement )
      {
        var uiText = iconRegion.CreateChild<UIText>();

        uiText.font = lib.font;
        uiText.fontSize = labelIconElement.fontScale == 1 ? lib.fontSize : lib.fontSize.GetMultiplied( labelIconElement.fontScale );
        uiText.locale = labelIconElement.locale;

        uiText.width  = UINumber.PW( 100 );
        uiText.height = UINumber.PH( 100 );
        uiText.left   = UINumber.EM( 0f );
        uiText.top    = UINumber.EM( 0f );

        uiText.position = UIPosition.Parent_Anchor;
        uiText.alwaysMinimumSize = false;
        uiText.HorizontalAlignment = HorizontalAlignment.Center;
        uiText.VerticalAlignment   = VerticalAlignment.Center;

        uiText.Uppercase = labelIconElement.fontIsUpperCase;
      }
    }
  }
}