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

namespace Rokojori
{ 
  public class SceneFileHeaderAttribute
  {  
    protected string _attributeName;

    public static SceneFileHeaderAttribute Create( string value )
    {
      var an = new SceneFileHeaderAttribute();
      an._attributeName = value;

      return an;
    }

    public SceneFileNamedValue GetAttribute( SceneFileHeader header )
    {
      return header.attributes.Find( a => a.name == _attributeName );
    }

    public string Get( SceneFileHeader header, string alternative = null )
    {
      var attribute = GetAttribute( header );

      if ( attribute == null )
      {
        return alternative;
      }

      return attribute.value.Substring( 1, attribute.value.Length - 2 );
    }

    public double GetNumberValue( SceneFileHeader header, double alternative = 0 )
    {
      var attribute = GetAttribute( header );

      if ( attribute == null )
      {
        return alternative;
      }

      return RegexUtility.ParseDouble( attribute.value );
    }

    
  }

  public class SceneFileHeaderAttributeValue:SceneFileHeaderAttribute
  { 
    public virtual void GetValue( SceneFileHeader header )
    {
    }
  }

  public class SceneFileHeaderAttributeValue<T>:SceneFileHeaderAttributeValue
  {
    T _value;

    public T value => _value;
    
    Func<SceneFileHeaderAttribute,SceneFileHeader,T> _getter;

    public SceneFileHeaderAttributeValue( string name, Func<SceneFileHeaderAttribute,SceneFileHeader,T> getter )
    {
      _attributeName = name;
      _getter = getter;
    }

    public override void GetValue( SceneFileHeader header )
    {
      _value = _getter( this, header );
    }


  }

  public class SFHStringAttribute:SceneFileHeaderAttributeValue<string>
  {
    public SFHStringAttribute( string name )
    :base( name, ( att, entry ) => att.Get( entry ) )
    {}

  }

  public class SFHNumberAttribute:SceneFileHeaderAttributeValue<double>
  {
    public SFHNumberAttribute( string name )
    :base( name, ( att, entry ) => att.GetNumberValue( entry ) )
    {}
  }
}