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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class TextureModule:ShaderGenerationModule
  { 
    public enum TextureChannelType
    {
      RGBA,
      RGB,
      ONE
    }

    public enum TextureChannelSource
    {
      R,
      G,
      B,
      A,
      CUSTOMIZABLE
    }

    public TextureChannelType _type;
    public TextureChannelSource _channelSource;

    public bool is1D => _type == TextureChannelType.ONE;

    public string _domainName;
    public string _domainValueName;
    public string _domainScaleName;
    public string _domainOffsetName;

    public bool _srgb = false;
    public bool _repeat = true;

    public enum DomainMode
    {
      Value,
      Texture,
      Texture_Scale,
      Texture_Scale_Offset
    }

    public DomainMode domainMode = DomainMode.Texture_Scale_Offset;
    public float domainOffsetDefault = 0;
    public float domainOffsetMin = -1;
    public float domainOffsetMax = 1;

    public float domainValueDefault = 0.5f;
    public float domainValueMin = 0;
    public float domainValueMax = 1;

    public enum TextureDefault
    {
      White, 
      Black
    }

    public TextureDefault _textureDefault = TextureDefault.White; 

    public TextureFilter _textureFilter = TextureFilter.Linear_MipMap_Anisotropic;

    public enum TextureFilter
    {
      Nearest,
      Nearest_MipMap,
      Nearest_MipMap_Anisotropic,
      Linear,
      Linear_MipMap,
      Linear_MipMap_Anisotropic
    }

    public virtual void GrabValues()
    {

    }

    public override List<ShaderCode> GetCode( ShaderGenerationContext context )
    {
      GrabValues();

      if ( ShaderPhase.Variables == context.phase )
      {
        var textureName = _domainName;

        var valuesDefinition = "";
        var samplerDefinition = "";
        

        if ( DomainMode.Value != domainMode )
        {
          var hints = new List<string>();

          if ( _srgb )
          {
            hints.Add( "source_color" );
          }
          
          hints.Add( TextureDefault.Black == _textureDefault ? "hint_default_black" : "hint_default_white" );
          hints.Add( _repeat ? "repeat_enable" : "repeat_disable" );
          hints.Add( "filter_" + ( _textureFilter + "" ).ToLower() );
          
          var textureSamplerName = _domainName + "Texture";

          samplerDefinition = UniformSampler( textureSamplerName, hints.Join() );

          if ( domainMode != DomainMode.Texture )
          {
            if ( is1D )
            {
              valuesDefinition += Uniform01( _domainScaleName, 1.0f );
            }
            else
            {
              valuesDefinition += Uniform( _domainScaleName, Colors.White );
            }

            valuesDefinition +="\n";
          }
        }        
        
        if ( DomainMode.Value == domainMode )
        {
          valuesDefinition += Uniform( _domainValueName, domainValueDefault, domainValueMin, domainValueMax );
        } 
        else if ( DomainMode.Texture_Scale_Offset == domainMode )
        {
          valuesDefinition += "\n";
          valuesDefinition += Uniform( _domainOffsetName, domainOffsetDefault, domainOffsetMin, domainOffsetMax );
          valuesDefinition += "\n";
        }

        

        

        var code = valuesDefinition + samplerDefinition;

        return AsUniformGroup( textureName, code );

      }

      return null;
    }
  }

}