using System.Collections;
using System.Collections.Generic;
using Godot;
using System;

using System.Threading.Tasks;

namespace Rokojori
{
  [Tool][GlobalClass]
  public partial class CrossBraces_Baker:_XX_MultiBakeModeBillboardBase
  {
    [Export]
    public int crossAngles = 2;
    [Export]
    public int crossBraces = 3;
    [Export]
    public float crossSpreadDistance = 1;
    [Export]
    public float crossAngleOffset = 0;

    [Export]
    public bool crossTop = false;

    [Export]
    public bool crossBottom = false;

    public override int GetNumViews()
    {
      var views = crossAngles * 2;

      if ( crossBottom )
      {
        views ++;
      }

      if ( crossTop )
      {
        views ++;
      }

      return views;
    }

    public override void CreateBakers()
    {
      var fov = multiBaker.GetCameraFOV();
      var distance = multiBaker.GetCameraDistance();
      var outputScale = multiBaker.GetOutputScale();

      RJLog.Log( "outputScale", outputScale );
      var _bakers = multiBaker.bakers;
      var mb = multiBaker;

      
      _bakers.ForEach(
        bk =>
        {
          var vs = bk.viewSettings;
          vs.fovDistance = Manual_BakingFDSettings.Create( fov, distance );          
          vs.rotationMode = BakingViewSettings.RotationMode.Yaw_Pitch;
        }
      );

      var index = 0;
      var mg = new MeshGeometry();  

      var numTextures = GetNumViews();
      var textureAlignment = TextureMerger.ComputeTextureAlignment( numTextures );
 

      if ( crossTop )
      {
        _bakers[ index ].viewSettings.yaw = 0 + crossAngleOffset;
        _bakers[ index ].viewSettings.pitch = 90f;        

        var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );

        var q = new MeshGeometry();        
        q.AddQuad( _bakers[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );  

        mg.Add( q );

        index ++;
      }

      if ( crossBottom )
      {
        _bakers[ index ].viewSettings.yaw = 0 + crossAngleOffset;
        _bakers[ index ].viewSettings.pitch = -90f;

        var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );
        var q = new MeshGeometry();
        q.AddQuad( _bakers[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );  

        mg.Add( q );

        index ++;
      }

      
      for ( int i = 0; i < crossAngles; i++ )
      {
        for ( int side = 0; side < 2; side ++ )
        {
          var angle = ( 180f * i ) / (float) crossAngles;

          _bakers[ index ].viewSettings.yaw = side == 0 ? angle : ( MathX.Repeat( angle + 180f, 360f ) );
          _bakers[ index ].viewSettings.yaw += crossAngleOffset;
          _bakers[ index ].viewSettings.pitch = 0;

          var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );          

          var q = new MeshGeometry(); 
          q.AddQuad( _bakers[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );  

          if ( crossBraces > 1 )
          {
            var normal = Vector3.Forward * _bakers[ index ].viewSettings.bakingRotation;
            var startOffset = normal * crossSpreadDistance * 0.5f;
            var endOffset = -startOffset;
            
            for ( int brace = 0; brace < crossBraces; brace ++ )
            {
              var bq = q.Clone();
              var lerpAmount = (float)brace / (float)( crossBraces - 1 );
              var offset = startOffset.Lerp( endOffset, lerpAmount );
              bq.ApplyTranslation( offset );
              mg.Add( bq );
            }
          }
          else
          {
            mg.Add( q );
          }


          index ++;
          
        }



      }

      
      mb.X_outputMesh.Mesh = mg.GenerateMesh();  
    }
  }
}