using Godot;
using System.Text;
using System.Reflection;

namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class GodotClassGenerator:Node
  {
    [Export]
    public string outputPath;

    [Export] 
    public bool exportFlag;

    [Export] 
    public string testClass;

    
    public override void _Process( double delta )
    {
      if ( exportFlag )
      {
        exportFlag = false;
        ExportFiles();
      }
    }

    void ExportFiles()
    {
      RJLog.Log( "Exporting:", testClass );
      var result = CreateClass( testClass );
      FilesSync.SaveUTF8( outputPath + "RJ" + testClass + ".cs", result );
    }

    public string CreateClass( string name )
    {
      var output = new StringBuilder();

      output.Append( "using Godot;\n" );
      output.Append( "\n" );
      output.Append( "namespace Rokojori\n" );
      output.Append( "{\n" );
      output.Append( "\n" );

      output.Append( "  [GlobalClass]\n");
      output.Append( "  public partial class RJ" + name + ":" + name + "\n");
      output.Append( "  {\n" );

    
      var classType = ReflectionHelper.GetTypeByNameFromAssembly( "Godot." + name, typeof( Node ).Assembly );

      if ( classType == null )
      {
        RJLog.Log( "Type is null" );
        return "";
      }

      output.Append( "  \n" );
      var bindingFlags = BindingFlags.Instance | BindingFlags.Public;
      EventInfo[] events = classType.GetEvents( bindingFlags );

      for ( int i = 0; i < events.Length; i++ )
      {
        var ev = events[ i ];
        var eventName = ev.Name;

        output.Append( "  \n" );
        output.Append( "  [Export]\n" );
        output.Append( "  public Action On" + eventName + ";\n" );
      }

      output.Append( "  \n" );

      output.Append( "  public override void _Ready()\n" );
      output.Append( "  {\n" );

      for ( int i = 0; i < events.Length; i++ )
      {
        var ev = events[ i ];
        var eventName = ev.Name;

        var parameters = classType.GetEvent( eventName ).EventHandlerType.GetMethod( "Invoke" ).GetParameters();

        var p = "( ";
        for ( int pn = 0; pn < parameters.Length; pn ++ )
        {
          if ( pn != 0 )
          {
            p += ", ";
          } 

          p += "p" + pn;
        }
        p += " )";
        

        output.Append( "    " + eventName + " += " + p + " => { Action.Trigger( On" + eventName +" ); }; \n" );
      }

      output.Append( "  }\n" );

      output.Append( "  }\n" );

      output.Append( "}\n" );

      RJLog.Log( output.ToString() );


      return output.ToString();
    }
  }
}