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

namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class Plane:Node3D
  {     
    [ExportToolButton( "Update Mesh")]
    public Callable UpdateMeshButton => Callable.From( () => UpdateMesh() );
    
    public readonly EventProperty<float> _width = new EventProperty<float>();
    [Export]
    public float width { get => _width.value; set => _width.value = value; }

    
    public readonly EventProperty<float> _height = new EventProperty<float>();
    [Export]
    public float height { get => _height.value; set => _height.value = value; }

    [Export]
    public bool extendBoundingBox = true;

    [Export]
    public float boundingBoxMinY = 0;

    [Export]
    public float boundingBoxMaxY = 1;

    [Export]
    public bool extendBoundingBoxToMax = true;
    
    public readonly EventProperty<__PlaneMeshType__> _type = new EventProperty<__PlaneMeshType__>();
    [Export]
    public __PlaneMeshType__ type { get => _type.value; set { _type.value = value; } }

    [Export]
    public Material material;

    [Export]
    public MeshInstance3D[] meshes;

    [Export]
    public bool snapXZ = true;

    [Export]
    public float snappingDistance = 100;

    [Export]
    public Vector3 snapOffset = Vector3.Zero;


    [ExportGroup( "Debug Info")]
    [Export]
    public int numTriangles;

    
    public override void _Process( double delta )
    {
      if ( ! snapXZ )
      {
        return;
      }

      GlobalPosition = Math3D.SnapRoundedXZ( GlobalPosition, snappingDistance, snappingDistance );
    }


    void UpdateMesh()
    {
      if ( _type == null )
      {
        return;
      }

      numTriangles = 0;
      this.LogInfo( "Creating mesh" );

      var mgs = _type.value.GetMeshGeometries( width, height );

      meshes = new MeshInstance3D[ mgs.Count ];

      Nodes.DestroyChildren( this );

      for ( int i = 0; i < mgs.Count; i++ )
      {
        var mg = mgs[ i ];
        
        var outputMesh = this.CreateChild<MeshInstance3D>( mg.name );
        outputMesh.Mesh = mg.GenerateMesh();
    

        if ( extendBoundingBox )
        {
          if ( extendBoundingBoxToMax )
          {
            outputMesh.CustomAabb = Box3.Create( Vector3.One * -100000, Vector3.One * 100000 );
          }
          else
          {
            var extendedBounds = (Box3) outputMesh.Mesh.GetAabb();
            extendedBounds.EnsureYBounds( boundingBoxMinY, boundingBoxMaxY );
            outputMesh.CustomAabb = extendedBounds;

          }

          
        }

        meshes[ i ] = outputMesh;

        numTriangles += mg.numTriangles;

        if ( material != null )
        {
          Materials.Set( outputMesh, material );
        }
      }
      
    }

  }
}