using Godot;
using System.Collections.Generic;

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

    public void Parse( SceneFileEntry entry )
    {

      line = entry.line.Substring( 1, entry.line.Length - 2 );

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

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

      lexer.GrabMatches( tokens, line );

      /*var info = "";
      tokens.ForEach(
        ( tk )=>
        {
          info += tk.type + " " + tk.match + "\n";
        }
      );*/

      var offset = 0;
      var token = tokens[ 0 ];
      
      if ( ! token.Is( LexerMatcherLibrary.CwordMatcher )  )
      {
        errorMessage = "First token is not a word: "+ token.type + " '" + token.match + "'";
        return;
      }

      var header = new SceneFileHeader();

      entry.header = header;

      header.type = tokens[ 0 ].match;

      offset = 1; token = tokens[ offset ];

      while ( offset < tokens.Count && token != null )
      {
        if ( ! token.Is( LexerMatcherLibrary.WhiteSpaceMatcher ) )
        {
          errorMessage = "Expected white space, but got: " + token.type + " '" + token.match + "'";
          return;
        }

        offset ++; token = tokens[ offset ];

        var assignmentResult = SceneFileLexer.ReadAssignment( tokens, offset );
        
        if ( assignmentResult.hasError )
        {
          errorMessage = assignmentResult.errorMessage;
          return;
        }

        header.attributes.Add( assignmentResult.GetNamedValue() );

        offset = assignmentResult.endOffset;
        token = tokens[ offset ];


        /*if ( ! token.Is( LexerMatcherLibrary.CwordMatcher ) )
        {
          errorMessage = "Expected word for attribute name, but got: " + token.type + " '" + token.match + "'";
          return;
        } 

        var attribute = new SceneFileNamedValue();
        attribute.name = token.match;

        offset ++; token = tokens[ offset ];

        if ( ! token.Is( LexerMatcherLibrary.OperatorMatcher, "=" ) )
        {
          errorMessage = "Expected assignment operator, but got:" + token.type + " '" + token.match + "'";
          return;
        } 

        offset ++; token = tokens[ offset ];

        if ( token.Is( LexerMatcherLibrary.NumberMatcher ) )
        {
          attribute.value = token.match;
          header.attributes.Add( attribute );

        }
        else if ( token.Is( LexerMatcherLibrary.DoubleQuotedStringMatcher ) )
        {
          attribute.value = token.match;
          header.attributes.Add( attribute );
        }
        else if ( token.Is( LexerMatcherLibrary.CFunctionMatcher ) )
        {
          var closer = LexerEvent.FindClosingBracket( tokens, offset + 1 );

          if ( closer.type != LexerEvent.FindResultType.Found )
          {
            errorMessage = "Function with unmatched brackets: " + token.type + " '" + token.match + "'";
            return;
          }

          for ( int i = offset; i <= closer.index; i++ )
          {
            attribute.value += tokens[ i ].match;
          }

          offset = closer.index + 1;
         
        }
        else
        {
          errorMessage = "Unexpected token:" + token.type + " '" + token.match + "'";
          return;
        }

        */

        offset ++; 

        token = ( offset < tokens.Count - 1 ) ? tokens[ offset ] : null ; 
        

      }


      //RJLog.Log( info );
       
      hasError = false;
    }
  }

}