
using Godot;
using Rokojori;
using System.Collections.Generic;
using System.Globalization;
using System;
using System.Data;

namespace Rokojori
{  
  [Tool]
  public partial class RokojoriPlugin:EditorPlugin
  {
    GizmoDrawerPlugin gizmoDrawerPlugin = new GizmoDrawerPlugin();

    public static readonly string path = "res://addons/rokojori_action_library";

    public static string Path( string path )
    {
      return RokojoriPlugin.path + "/" + path;
    }

    public static string GlobalizedPath( string path )
    {
      return ProjectSettings.GlobalizePath( Path( path ) );
    }

    static readonly string RokojoriRootAutoLoad = "RokojoriRootAutoLoad";
    static readonly string RokojoriRootAutoLoadPath = Path( "Runtime/Godot/Root.cs" );
    static readonly string RokojoriProjectInternalPath = "res://.rokojori";
    static readonly string RokojoriSettingsPath = "res://.rokojori/settings";
    static readonly string RokojoriCachePath = "res://.rokojori/cache";

    // static RokojoriPlugin _instance;
    // public static RokojoriPlugin Get()
    // {
    //   return _instance;
    // }

    public override void _EnablePlugin()
    {
      this.LogInfo();
      AddAutoloadSingleton( RokojoriRootAutoLoad, RokojoriRootAutoLoadPath );

     
      EnsureHiddenProjectPath( RokojoriProjectInternalPath );
      EnsureHiddenProjectPath( RokojoriSettingsPath );
      EnsureHiddenProjectPath( RokojoriCachePath );

    }

    static string CreateTemporaryFilePath()
    {
      var directory = RokojoriCachePath + "/temp";

      EnsureHiddenProjectPath( directory );
      var id = IDGenerator.GenerateID();

      return directory + "/" + id;

    }

    public static string SaveTemporaryJSON( object json )
    {
      var path = ProjectSettings.GlobalizePath( CreateTemporaryFilePath() );
      var result = FilesSync.SaveJSON( path, json );

      return path;
    }

    public static string SaveTemporaryUTF8( string text )
    {
      var path = ProjectSettings.GlobalizePath( CreateTemporaryFilePath() );
      var result = FilesSync.SaveUTF8( path, text );

      return path;
    }

    static void EnsureHiddenProjectPath( string resPath )
    {
      var gdIgnorePath = resPath + "/.gdignore" ;
      FilesSync.EnsureDirectoryExists( ProjectSettings.GlobalizePath( resPath ) );

      if ( ! FilesSync.FileExists( ProjectSettings.GlobalizePath( gdIgnorePath ) ) )
      {
        FilesSync.SaveUTF8( ProjectSettings.GlobalizePath( gdIgnorePath ), "" );
      }
    }

    static void EnsureCachedProjectPath( string cachePath )
    {
      
    }


    public override void _DisablePlugin()
    {
      this.LogInfo();
      RemoveAutoloadSingleton( RokojoriRootAutoLoad );
    }

    
    static readonly string ProblemsExplorerPath = "res://addons/rokojori_action_library/Tools/Messages/Messages.tscn";
    static Control messages; 

    public override void _EnterTree()
    {
      // _instance = this;

      EnsureHiddenProjectPath( RokojoriProjectInternalPath );
      EnsureHiddenProjectPath( RokojoriSettingsPath );
      EnsureHiddenProjectPath( RokojoriCachePath );

      this.LogInfo();

      AddNode3DGizmoPlugin( gizmoDrawerPlugin );

      // var pePackedScene = GD.Load<PackedScene>( ProblemsExplorerPath );

      // if ( pePackedScene != null )
      // {
      //   //  this.LogInfo( "Problems Explorer found: ", pePackedScene );

      //   messages = ((PackedScene)pePackedScene).Instantiate<Control>();

      //   var ui = messages.Get<UI>();
      //   ui.BindOwnChildren();



      //   var shortCut = new Shortcut();
      //   shortCut.Events = [ new InputEventKey{ CtrlPressed = true, Keycode = Key.U } ];

      //   AddControlToDock( DockSlot.RightBr, messages, shortCut );
      // }
      // else
      // {
      //   this.LogInfo( "Problems Explorer not found: ", ProblemsExplorerPath );
      // }
    }

    public override void _ExitTree()
    {
      this.LogInfo();

      if ( messages != null )
      {
        RemoveControlFromDocks( messages );
      }

      RemoveNode3DGizmoPlugin( gizmoDrawerPlugin );
    }

    bool wasDisposed = true;

    public RokojoriPlugin()
    {
      wasDisposed = true;
    }

    public class MarkerData
    {
      public DateTime time;
    }

    static readonly string markerPath = "reload-marker.json";

   

    protected override void Dispose( bool disposing )
    {

      var markerData = new MarkerData();
      markerData.time = DateTime.Now;

      SaveCache( markerPath, markerData );
    }

    float reloadDuration = 2;
    DateTimeOffset lastUpdateTime = DateTime.Now;
    DateTimeOffset lastDisposalTime = DateTime.Now;

    public void SaveCache( string relativeCachePath, object data )
    { 
      var path = RokojoriCachePath + "/" + relativeCachePath;

      FilesSync.SaveJSON( ProjectSettings.GlobalizePath( path ), data );
    }

    public T LoadCache<T>( string relativeCachePath ) where T:new()
    {  
      var path = RokojoriCachePath + "/" + relativeCachePath;

      return FilesSync.LoadJSON<T>( ProjectSettings.GlobalizePath( path ));
    }

    public T LoadSettings<T>( string relativeSettingsPath ) where T:new()
    {  
      var path = RokojoriSettingsPath + "/" + relativeSettingsPath;

      return FilesSync.LoadJSON<T>( ProjectSettings.GlobalizePath( path ));
    }

    UI editingSceneUI = null;
    UIRegion editingSceneRegion = null;

    public override void _Process( double delta )
    {
      var editingScene = EditorInterface.Singleton.GetEditedSceneRoot();

      if ( lastUpdateTime.HasExpired( reloadDuration ) )
      { 
        lastUpdateTime = DateTime.Now;

        var markerData = LoadCache<MarkerData>( markerPath );

        if ( markerData != null && markerData.time != lastDisposalTime )
        {
          lastDisposalTime = markerData.time;
          
          editingScene.ForEach<IAssemblyReload>( ar => ar.OnAssemblyReloaded() );

          if ( messages != null )
          {
            messages.ForEach<IAssemblyReload>( ar => ar.OnAssemblyReloaded() );
          }
        }
      } 

      if ( editingScene is UIRegion region && ! ( editingScene is UI ) )
      {
        if ( editingSceneRegion != region )
        {
          if ( editingSceneUI != null )
          {
            editingSceneUI.DeleteSelf();
            editingSceneUI = null;
          }

          editingSceneRegion = region;
          editingSceneUI = this.CreateChild<UI>();
          editingSceneUI.settings = region.uiSettings;

          editingSceneUI.BindChildrenOf( region );
        }  

        editingSceneUI.updateMode = UI.UpdateMode.Only_Manual_Updates;

        if ( region.reassignUI )
        {
          editingSceneUI.settings = region.uiSettings;
          region.SetUI( editingSceneUI );
          editingSceneUI.BindChildrenOf( region );
          region.reassignUI = false;
        }

        if ( region.updateInEditor )
        {
          region.SetUI( editingSceneUI );
          editingSceneUI.BindChildrenOf( region );
          editingSceneUI.fontZoom = region.fontZoom;

          editingSceneUI.UpdateExternal( (float)delta );
          region.Layout();
          region.computedFontSize = editingSceneUI.X_computedFontSizePixels;
        }

        
      } 

      
    }
  }
}