using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;


#if TOOLS

namespace Rokojori.Tools
{
  public class GLTFExport
  {
    static string temporaryPath = "res://.rokojori/cache/temp";

    public static void Save( Node3D node, string path, string texturesPath = null, string binPath = null )
    {      
      
      if ( ! path.EndsWith( ".gltf" ) )
      {
        if ( path.EndsWith( ".glb" ) )
        {
          path.ReplaceEnd( ".glb", ".gltf" );
        }
        else
        {
          path += ".gltf";
        }
      }

      FilesSync.EnsureParentDirectoryExists( path );

      if ( binPath != null )
      {
        FilesSync.EnsureDirectoryExists( binPath );
      }

      if ( texturesPath != null )
      {
        FilesSync.EnsureDirectoryExists( texturesPath );
      }
      

      var state = new GltfState();

      var doc = new GltfDocument();
      doc.AppendFromScene( node, state );
      
      if ( texturesPath == null )
      {
        doc.WriteToFilesystem( state, path );
        return;
      }

      var gltfFilePath = FilePath.Absolute( path ); // Defines file name and gltfPath;
      var gltfParentFilePath = gltfFilePath.CreateAbsoluteParent();
      var texturesDirPath = FilePath.Absolute( texturesPath ); // Only directory for textures
      var binDirPath = binPath == null ? gltfParentFilePath : FilePath.Absolute( binPath ); // Only directory for bins, name comes from gltf.

      var temporaryFilePath = FilePath.Create( ProjectSettings.GlobalizePath( temporaryPath ) + "/" + gltfFilePath.fullFileName );
      var temporaryDirPath = temporaryFilePath.CreateAbsoluteParent();

      doc.WriteToFilesystem( state, temporaryFilePath.fullPath );

      var earlyOut = false;

      if ( earlyOut )
      {
        return;
      }

      var json = JSON.Load( temporaryFilePath.fullPath ).AsObject();

      var images = json.GetArray( "images" );

      for ( int i = 0; images != null && i < images.size; i++ )
      {
        var image = images.Get( i ).AsObject();
        var uri = image.GetString( "uri" ).Replace( "%2F", "/" );

        var textureFilePath = temporaryDirPath.MakeRelative( uri );
        var newTexturesFilePath = texturesDirPath.MakeRelative( textureFilePath.fullFileName );
        var newRelativeFilePath = gltfParentFilePath.MakeAbsolutePathRelative( newTexturesFilePath.fullPath );

         
        // RJLog.Log( "Moving image", i, uri, newRelativeFilePath.path,"\n" +  textureFilePath.fullPath, "\n" + newRelativeFilePath.fullPath );
        image.Set( "uri", newRelativeFilePath.path.Replace( "/", "%2F" ) );

        if ( ! newRelativeFilePath.Exists() )
        {
          FilesSync.Move( textureFilePath.fullPath, newTexturesFilePath.fullPath ); 
        }
        
      }

      var buffers = json.GetArray( "buffers" );

      for ( int i = 0; buffers != null && i < buffers.size; i++ )
      {
        var buffer = buffers.Get( i ).AsObject();
        var uri = buffer.GetString( "uri" ).Replace( "%2F", "/" );

        var bufferFilePath = temporaryDirPath.MakeRelative( uri );
        var newBufferFilePath = binDirPath.MakeRelative( gltfFilePath.WithExtension( ".bin" ).fullFileName );
        var newRelativeFilePath = gltfParentFilePath.MakeAbsolutePathRelative( newBufferFilePath.fullPath );

        // RJLog.Log( "Moving buffer", i, uri, newRelativeFilePath.path, bufferFilePath.fullPath, newRelativeFilePath.fullPath );
        buffer.Set( "uri", newRelativeFilePath.path.Replace( "/", "%2F" ) );
        FilesSync.Move( bufferFilePath.fullPath, newBufferFilePath.fullPath ); 
      }

      JSON.Save( gltfFilePath.fullPath, json );
      FilesSync.Delete( temporaryFilePath.fullPath );

      return;
    }
  }
}

#endif