using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Rokojori
{
  public class LexerMatcher
  {
    public static readonly string FullTypeDelimiter = "|";
    string _mode;
    public string mode => _mode;
    
    string _type;
    public string type => _type;

    string _fullType;
    public string fullType 
    {
      get
      {
        if ( _fullType != null )
        {
          return _fullType;
        }

        _fullType = _mode == "" ? _type : ( _mode + LexerMatcher.FullTypeDelimiter + _type );

        return _fullType;
      }
    }


    string _nextMode;
    public string nextMode => _nextMode;

    Regex _matcher;
    public Regex matcher 
    {
      get { return this._matcher; }
    }

    public bool Matches( LexerEvent le )
    {
      return fullType == le.type;
    }

    public bool Matches( string type )
    {
      return fullType == type;
    }

    public RegexMatches GetRegexMatches( string source )
    {
      return new RegexMatches( matcher.Match( source, 0 ) );
    }

    public RegexMatches GetRegexMatches( LexerEvent le )
    {
      return GetRegexMatches( le.match );
    }

    public LexerMatcher( string type, Regex matcher, string mode = "", string nextMode = "" )
    {
      _type = type;
      _mode = mode;
      _nextMode = nextMode;
      _matcher = RegexUtility.MakeSticky( matcher );
    } 

    public LexerMatcher( string type, string matcher, string mode = "", string nextMode = "" )
    {
      _type = type;
      _mode = mode;
      _nextMode = nextMode;
      _matcher = RegexUtility.MakeSticky( new Regex( matcher ) );
    } 

    public static LexerMatcher CreateExtended( string type, string matcher, string mode = "", string nextMode = "" )
    {
      return new LexerMatcher( type, RegexExtensions.Extend( matcher ), mode, nextMode );
    } 
 
    public LexerMatcher CloneWithModes( string mode, string nextMode )
    {
      return new LexerMatcher( _type, _matcher, mode, nextMode );
    }

    public LexerMatcher WithModes( string mode, string nextMode = null )
    {
      if ( nextMode == null )
      {
        nextMode = mode;
      }
      
      return new LexerMatcher( _type, _matcher, mode, nextMode );
    }

    public LexerMatcher WithNext( string nextMode )
    {
      return new LexerMatcher( _type, _matcher, mode, nextMode );
    }

    public int MatchLength( string source, int offset )
    {
      var match = matcher.Match( source, offset );

      if ( match.Success && match.Index != offset )
      {
        var message = "Illegal match index! Not a sticky matcher: " + matcher + ".";
        message += "Offset: " + offset + " Matched Index: " + match.Index ;
        throw new System.Exception( message );
      }

      if ( match.Success )
      {
        return match.Groups[ 0 ].Length;
      }

      return -1;
    }

  }
}