using Godot;
using System.Collections.Generic;

namespace Rokojori
{  
  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Sensor.svg")]
  public partial class InputIconsLibrary: Resource
  {  
    [Export]
    public Font font;
    
    [Export]
    public UINumber fontSize;

    [Export]
    public float iconHeightInEm = 2f; 

    [ExportGroup("Mouse & Keyboard")]
    [Export]
    public MouseInputIconDefinition mouseInputIcon;

    [Export]
    public DefaultInputIconDefinition keyboardKeys;

    [Export]
    public DefaultInputIconDefinition keyboardModifiers;

    [Export]
    public DefaultInputIconDefinition keyboardSpaceKey;

    [Export]
    public DefaultInputIconDefinition keyboardEnterKey;

    [ExportGroup("GamePad")]

    [Export]
    public DefaultInputIconDefinition mainButtons;

    [Export]
    public DefaultInputIconDefinition leftShouldersButtons;

    [Export]
    public DefaultInputIconDefinition rightShouldersButtons;

    [Export]
    public DirectionalInputIconDefinition digitalPad;

    [Export]
    public DirectionalInputIconDefinition leftJoystick;

    [Export]
    public DirectionalInputIconDefinition rightJoystick;
  
    
    [ExportGroup("Touchpad")]

    [Export]
    public DefaultInputIconDefinition touchClick;

    [Export]
    public DefaultInputIconDefinition touchHold;

    [Export]
    public DirectionalInputIconDefinition swipeGesture;


    [ExportGroup("Combined")]
    [Export]
    public CombinedIconsDefinition combinedInputs;

    
    [ExportGroup("Localization")]
    [Export]
    public InputIconLocale[] locales = new InputIconLocale[ 0 ];

    public LocalizedString GetInputLabel( InputIcon icon )
    {
      var index = Arrays.FindIndex( locales, il => il.icon.Equals( icon ) );

      if ( index != -1 )
      {
        return locales[ index ].locale;
      }

      return icon.GetDefaultLocale();

    }

    public List<InputIconDefinition> GetAllDefinitions()
    {
      var list = new List<InputIconDefinition>()
      {
        mouseInputIcon, keyboardKeys,
        
        mainButtons, leftShouldersButtons, rightShouldersButtons, 
        digitalPad, leftJoystick, rightJoystick,

        touchClick, touchHold, swipeGesture,
        
        combinedInputs
      };

      list = Lists.Filter( list, l => l != null );

      return list;
    }

    public List<InputIcon> ResolveIcons( InputIcon[] icons )
    {
      var list = new List<InputIcon>();

      for ( int i =0 ; i < icons.Length; i++ )
      {
        var icon = icons[ i ];
                
        if ( icon is SensorIcon sensorIcon )
        {
          var sensor = sensorIcon.sensor;

          if ( sensor == null )
          {
            continue;
          }

          list.AddRange( sensor.GetInputIcons() );
          
        }
        else
        {
          list.Add( icon );
        }

      }

      var definitions = GetAllDefinitions();

      var resolvedList = new List<InputIcon>();

      for ( int i = 0; i < list.Count; i++ )
      {
        var d = definitions.Find( d => d.ResolveIcons( i, list ) != -1 );

        if ( d == null )
        {
          resolvedList.Add( list[ i ] );
        }
        else
        {
          var resolvedIcon = new CombinedIcon();
          var length = d.ResolveIcons( i, list );
          resolvedIcon.icons = list.GetRange( i, length ).ToArray();
          i += length - 1;

          resolvedList.Add( resolvedIcon );
        }
      }

      return resolvedList;
    }

    public InputIconDefinition GetInputIconDefinition( InputIcon icon )
    {
      if ( icon is MouseInputIcon )
      {
        return mouseInputIcon;
      } 
      else if ( icon is KeyIcon keyIcon)
      {
        if ( Key.Enter == keyIcon.key )
        {
          return keyboardEnterKey;
        }

        if ( Key.Space == keyIcon.key )
        {
          return keyboardSpaceKey;
        }

        if ( KeySensor.IsModifierKey( keyIcon.key ) )
        {
          return keyboardModifiers;
        }

        return keyboardKeys;
      }
      else if ( icon is GamePadButtonIcon gpButtonIcon )
      { 
        if ( JoyButton.LeftShoulder == gpButtonIcon.button )
        {
          return leftShouldersButtons;
        }

        if ( JoyButton.RightShoulder == gpButtonIcon.button )
        {
          return rightShouldersButtons;
        }

        if ( JoyButton.DpadLeft  == gpButtonIcon.button ||
             JoyButton.DpadRight == gpButtonIcon.button ||
             JoyButton.DpadUp    == gpButtonIcon.button ||
             JoyButton.DpadDown  == gpButtonIcon.button 
        )
        {
          return digitalPad;
        }

        return mainButtons;

      }
      else if ( icon is GamePadAxisIcon gpAxisIcon)
      { 
        if ( JoyAxis.LeftX  == gpAxisIcon.axis ||  JoyAxis.LeftY == gpAxisIcon.axis )
        {
          return leftJoystick;
        }

        if ( JoyAxis.RightX  == gpAxisIcon.axis ||  JoyAxis.RightY == gpAxisIcon.axis )
        {
          return rightJoystick;
        }

        if ( JoyAxis.TriggerLeft  == gpAxisIcon.axis  )
        {
          return leftShouldersButtons;
        }

        if ( JoyAxis.TriggerRight == gpAxisIcon.axis )
        {
          return rightShouldersButtons;
        }
      }


      var definitions = GetAllDefinitions();

      return definitions.Find( d => d.HasIconFor( icon ) );      
    }

  }
}