using Godot;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class LODHeightMapGeometry:LODParent
  {
    [Export]
    public float size = 500;

    [Export]
    public float height = 1000;

    [Export]
    public int resolution = 128;

    [Export]
    public float noiseScale = 0.0025f;

    [Export]
    public float noiseScaleAmount = 10f;

    [Export]
    public float noiseScale2 = 0.025f;

    [Export]
    public float noiseScale2Amount = 1f;

        [Export]
    public float noiseScale3 = 0.15f;

    [Export]
    public float noiseScale3Amount = 0.1f;

    [Export]
    public int levels = 6;

    [Export]
    public Material material;

    public void Create()
    {
      var hmd = HeightMapData.Create( resolution, resolution );

      var offsetX = GlobalPosition.X - size/2f;
      var offsetY = GlobalPosition.Z - size/2f;

      var weights = noiseScaleAmount + noiseScale2Amount + noiseScale3Amount;

      for ( int i = 0; i < 128; i ++ )
      {
        for ( int j = 0; j < 128; j++ )
        {
          var x = i / (float)resolution * size + offsetX;
          var y = j / (float)resolution * size + offsetY;

          var v = Noise.Perlin( new Vector2( x, y ) * noiseScale ) * noiseScaleAmount ;
          var v2 = Noise.Perlin( new Vector2( x, y ) * noiseScale2 ) * noiseScale2Amount;
          var v3 = Noise.Perlin( new Vector2( x, y ) * noiseScale3 ) * noiseScale3Amount;

          hmd.Set( i, j, ( v + v2 + v3 ) / weights );
        }
      }

      var level = 1;
      var ratio = size / resolution;
      var scale = new Vector3( ratio * level, height, ratio * level );

      var meshInstance3D = this.CreateChild<MeshInstance3D>();
      meshInstance3D.Mesh = hmd.GenerateMeshGeometry( scale ).GenerateMesh();
      Materials.Set( meshInstance3D, material );

      var offset = size / -2;
      meshInstance3D.Position = new Vector3( offset, 0, offset );

      var levelScale = 2;

      var meshes = new List<Node3D>();

      meshes.Add( meshInstance3D );

      while ( level < levels )
      {
        hmd = hmd.CreateLowerResolution();
        level ++;

        scale = new Vector3( ratio * levelScale , height, ratio * levelScale );

        var lowMeshInstance3D = this.CreateChild<MeshInstance3D>();
        lowMeshInstance3D.Mesh = hmd.GenerateMeshGeometry( scale ).GenerateMesh();

        Materials.Set( lowMeshInstance3D, material );

        lowMeshInstance3D.Position = new Vector3( offset, 0, offset );

        levelScale *= 2;

        meshes.Add( lowMeshInstance3D );
      }

      lods = meshes.ToArray();
      
    }
  }
}