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



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class GenerateInBox:GeneratorScatterer
  {
    [Export]
    public Node3D cornerA;
    [Export]
    public Node3D cornerB;

    [Export]
    public bool xzOnly = true;
    [Export]
    public float density = 1;

    [Export]
    public bool snapToWorldGrid = false;

    protected override List<ScatterPoint> _Scatter( List<ScatterPoint> points, Scatterer root )
    {
      CreateWeights();
      
      var minPosition = Math3D.MinLocalPosition( cornerA, cornerB );
      var maxPosition = Math3D.MaxLocalPosition( cornerA, cornerB );

      if ( snapToWorldGrid )
      {
        var snapping = Vector3.One / density;
        minPosition = minPosition.SnapCeiled( snapping ); 
        maxPosition = maxPosition.SnapFloored( snapping ); 
      }

      var pointsX = Mathf.CeilToInt( ( maxPosition.X - minPosition.X ) * density );
      var pointsY = Mathf.CeilToInt( ( maxPosition.Y - minPosition.Y ) * density );
      var pointsZ = Mathf.CeilToInt( ( maxPosition.Z - minPosition.Z ) * density );
      
      var id = 0;

      if ( xzOnly )
      {        
        var y = ( cornerA.Position.Y + cornerB.Position.Y ) / 2f;
        
        for ( int x = 0; x < pointsX; x++ )
        {
          var xPosition = MathX.Map( x, 0, pointsX - 1, minPosition.X, maxPosition.X );

          for ( int z = 0; z < pointsZ; z++ )
          {
            var zPosition = MathX.Map( z, 0, pointsZ- 1, minPosition.Z, maxPosition.Z );

            id = CreatePoint( points, id, xPosition, y, zPosition );
          }
        }
      }
      else
      {        

        for ( int x = 0; x < pointsX; x++ )
        {
          var xPosition = MathX.Map( x, 0, pointsX - 1, minPosition.X, maxPosition.X );

          for ( int y = 0; y < pointsY; y++ )
          { 
            var yPosition = MathX.Map( y, 0, pointsY- 1, minPosition.Y, maxPosition.Y );

            for ( int z = 0; z < pointsZ; z++ )
            {
              var zPosition = MathX.Map( z, 0, pointsZ- 1, minPosition.Z, maxPosition.Z );

              id = CreatePoint( points, id, xPosition, yPosition, zPosition );
            }
          }
        }
      }

      return points;
    }

    int CreatePoint( List<ScatterPoint> points, int id, float x, float y, float z )
    {
      var p = new ScatterPoint( this, id++ );

      p.position = new Vector3( x, y, z );      
      p.useGlobalPosition = false;
    
      p.visible = ! setDiscarded;
      p.seed = Noise.CreateSeed( p.position );

      AssginSceneAndContainer( p );

      points.Add( p );

      return id;
    } 


  }
}