using Godot;
using System.Collections.Generic;

namespace Rokojori
{
  public class SceneFileMemberParser
  {
    public bool hasError = true;
    public string errorMessage;
    string line;

    public void Parse( SceneFileEntry entry )
    {
      line = entry.line;

      var lexer = new SceneFileLexer();
      var tokens = lexer.LexToList( line );

      if ( lexer.hasError || tokens.Count == 0)
      {
        errorMessage = "Lexing failed";
        return;
      }

      tokens.RemoveAll( t => t.isDone );



      lexer.GrabMatches( tokens, line );

      if ( ! tokens[ 0 ].Is( LexerMatcherLibrary.CwordMatcher ) )
      {
        hasError = true;
        errorMessage = RJLog.Stringify( "Expected name as first token, got:", tokens[ 0 ].type, ">>",tokens[ 0 ].match );

        return;
      }

      var assignmentOpResult = LexerEvent.Find( tokens, 1, 
        t => 
        { 
          if ( t.Is( LexerMatcherLibrary.OperatorMatcher, "=" ) )
          {
            return LexerEvent.FindResultType.Found;
          }

          if ( t.Is( LexerMatcherLibrary.WhiteSpaceMatcher ) )
          {
            return LexerEvent.FindResultType.KeepSearching;
          }

          return LexerEvent.FindResultType.Error;

        }
      );

      if ( LexerEvent.FindResultType.Found != assignmentOpResult.type )
      {
        hasError = true;
        errorMessage = RJLog.Stringify( "Expected assignment operator:", tokens )  ;
        return;
      }

      var namedValue = new SceneFileNamedValue();
      entry.member = namedValue;


      namedValue.name = tokens[ 0 ].match;

      var valueIndexResult = LexerEvent.Find( tokens, assignmentOpResult.index + 1, 
        	( t )=>
          { 
            if ( t.Is( LexerMatcherLibrary.WhiteSpaceMatcher ) )
            {
              return LexerEvent.FindResultType.KeepSearching;
            }

            return LexerEvent.FindResultType.Found;
          }
      );

      if ( LexerEvent.FindResultType.Found != valueIndexResult.type )
      {
        hasError = true;
        errorMessage = RJLog.Stringify( "Expected value after assignment at ", assignmentOpResult.index, "in", tokens )  ;
        return;
      }

      namedValue.value = LexerEvent.GetMatchFromRange( tokens, valueIndexResult.index );

      var isList = tokens[ valueIndexResult.index ].Is( LexerMatcherLibrary.BracketMatcher, "[" );

      if ( ! isList )
      {
        namedValue.valueData = new SceneFileValue();
        namedValue.valueData.ParseValue( tokens, valueIndexResult.index, tokens.Count - valueIndexResult.index );
        return;
      }

      if ( isList ){ return; }

      var separators = LexerEvent.GetSeparatorsInBrackets( tokens, valueIndexResult.index );

      var lastIndex = valueIndexResult.index + 1;

      namedValue.valuesData = new List<SceneFileValue>();

      for ( int i = 0; i < separators.Count; i++ )
      {
        var v = new SceneFileValue();
        v.ParseValue( tokens, lastIndex, separators[ i ] - lastIndex );
        namedValue.valuesData.Add( v );

        lastIndex = separators[ i ] + 1;
      } 

      var lastV = new SceneFileValue();
      lastV.ParseValue( tokens, lastIndex, ( tokens.Count - 1 ) - lastIndex );





    }
  }

}