using Cryville.Common.Collections.Generic;
using Cryville.Common.Pdt;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Cryville.Crtr.Ruleset {
	internal class RulesetInterpreter : PdtInterpreter {
		public RulesetInterpreter(string src, Binder binder) : base(src, binder) { }

		readonly List<RulesetSelector> s = new List<RulesetSelector>();
		readonly HashSet<string> a = new HashSet<string>();
		protected override object InterpretKey(Type type) {
			if (PairCollection<JudgeAction, PdtExpression>.IsPairCollection(type))
				return InterpretJudgeAction();
			else if (type == typeof(Constraint))
				return InterpretConstraintKey();
			else
				return base.InterpretKey(type);
		}
		object InterpretJudgeAction() {
			a.Clear();
			while (true) {
				int pp = Position;
				switch (cc) {
					case '@':
						GetChar();
						a.Add(GetIdentifier());
						break;
					default:
						return JudgeAction.Construct(a, (string)base.InterpretKey(null));
				}
				ws();
				if (Position == pp) throw new FormatException("Invalid judge action format.");
			}
		}
		object InterpretConstraintKey() {
			s.Clear(); a.Clear();
			string key = "";
			while (true) {
				int pp = Position;
				switch (cc) {
					case '@':
						GetChar();
						a.Add(GetIdentifier());
						break;
					case '$':
						GetChar();
						s.Add(new RulesetSelector.CreateItem());
						key = null;
						break;
					case '#':
						GetChar();
						s.Add(new RulesetSelector.Index());
						break;
					case '>':
						GetChar();
						s.Add(new RulesetSelector.Property(GetExp()));
						break;
					case ';':
					case ':':
						return new ConstraintKey(a.Contains("var") ? ConstraintType.Variable : ConstraintType.Property, key);
					case '{':
						return new RulesetSelectors(s);
					case '}':
						return null;
					default:
						var p4 = GetIdentifier();
						s.Add(new RulesetSelector.EventType(p4));
						if (key != null) key += p4;
						break;
				}
				ws();
				if (Position == pp) throw new FormatException("Invalid selector or key format.");
			}
		}
	}
}
