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



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class QuadBillboardMeshGenerator:MeshInstance3D
  { 
    [Export]
    public float quadSize = 0.0001f;

    List<int> _updateIDs = new List<int>();
    SerializedGodotObject _cachedObject;

    public override void _Process( double delta )
    {
      Generate();
    }

    public void Generate()
    {      
      var currentObject = SerializedGodotObject.Create( this );

      var changed =  ! currentObject.Equals( _cachedObject );

      if ( ! changed )
      {
        var updateList = Lists.Map( Nodes.GetDirectChildren<QuadBillboardDataProcessor>( this ), p => p.UpdateID() );

        if ( updateList.Count == _updateIDs.Count )
        {
          for ( int i = 0; ! changed && i < _updateIDs.Count; i++ )
          {
            if ( _updateIDs[ i ] != updateList[ i ] )
            {
              changed = true;
            }
          }
          
        }
        else
        {
          changed = true;
        }

        if ( changed )
        {
          _updateIDs = updateList;
        }      
      }

      if ( ! changed )
      {
        return;
      }

      _cachedObject = currentObject;


      var list = new List<QuadBillboardData>();

      this.OnAllDirectChildren<QuadBillboardDataProcessor>(
        ( p )=>
        {
          list = p.Process( list );
        }
      );

      GenerateMesh( list );
    }

    void GenerateMesh( List<QuadBillboardData> data )
    {
      if ( data.Count == 0 )
      {
        RJLog.Log( "Not Creating" ); 
        return;
      }

      RJLog.Log( "Creating:", data.Count ); 

      var mg = new MeshGeometry();

      data.ForEach(
        ( qd )=>
        {
          if ( ! qd.visible )
          {
            return;
          }

          var q = MeshGeometry.BillboardQuad( quadSize );

          q.ApplyTransform( qd.globalTransform3D );

          mg.Add( q );
        }
      );

      Mesh = mg.GenerateMesh();
    }
  }
}