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

namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class LODNode:MeshInstance3D
  {

    [Export]
    public LODArrangement arrangement;

    [Export]
    public int currentLevelIndex = -1;

    [Export]
    public int drawElements = 0;

    [Export]
    public float distanceScale = 1;

    [Export]
    public MeshInstance3D lod0;

    LODLevel _currentLevel;

    public override void _Process( double delta ) 
    {
      if ( arrangement == null )
      {
        return;
      }

      _hasCameraDirection = false;
      _hasDistance = false;
      _hasPitch = false;
      _hasYaw = false;

      var level = arrangement.GetLevel( this );

      if ( level == _currentLevel )
      {
        return;
      }

      currentLevelIndex = arrangement.levels.IndexOf( level );

      if ( lod0 != null )
      {
        lod0.Visible = currentLevelIndex == 0;
      }

      if ( ! faceCount.ContainsKey( level.mesh ) )
      {
        if ( level.mesh is ArrayMesh am )
        {
          faceCount[ level.mesh ] = am.SurfaceGetArrayIndexLen( 0 );
        }
        else
        {
          faceCount[ level.mesh ] = level.mesh.GetFaces().Length;
        }

        
      }

      drawElements = faceCount[ level.mesh ];
      Mesh = level.mesh;
      MaterialOverride = level.material;
    }

    Dictionary<Mesh,int> faceCount = new Dictionary<Mesh,int>();


     public Camera3D camera 
    {
      get 
      {
        var _camera = GetViewport().GetCamera3D();

#if TOOLS 

        if ( Engine.IsEditorHint() )
        {
          _camera = EditorInterface.Singleton.GetEditorViewport3D().GetCamera3D();
        }
      
#endif

        return _camera;

      }

    }

    bool _hasCameraDirection = false;
    Vector3 _cameraDirection;

    public Vector3 cameraDirection
    {
      get
      {
        if ( _hasCameraDirection )
        {
          return _cameraDirection;
        }

        _cameraDirection = ( GlobalPosition - camera.GlobalPosition );

        _hasCameraDirection = true;

        return _cameraDirection;
      }
    }

    bool _hasDistance = false;
    float _distance = 0;
  
    public float distance 
    {
      get 
      {
        if ( _hasDistance )
        {
          return _distance * distanceScale;
        }

        _distance = cameraDirection.Length();

        _hasDistance = true;

        return _distance * distanceScale;
      }
    }

    bool _hasPitch = false;
    float _pitch = 0;

    public float pitch 
    {
      get 
      {
        if ( _hasPitch )
        {
          return _pitch;
        }

        _pitch = Math3D.GlobalPitch( cameraDirection );

        _hasPitch = true;

        return _pitch;
      }
    }

    bool _hasYaw = false;
    float _yaw = 0;

    public float yaw 
    {
      get 
      {
        if ( _hasYaw )
        {
          return _yaw;
        }

        _yaw = Math3D.GlobalYaw( cameraDirection );

        _hasYaw = true;

        return _yaw;
      }
    }

    

  
  }
}