using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;

namespace Logic {
    public class Condition {
        public enum Type {
            have,   // A > 0
            equal,  // A = B
            more,   // A > B
            emore,  // A >= B
            less,   // A < 0
            eless,  // A <= B
            nonequal,   // A != B
        }
    
        [JsonProperty("valueA")]
        public string valueA; // id of item or number - value B

        [JsonProperty("valueB")]
        public string valueB; // id of item or number - value B

        [JsonProperty("condition")]
        [JsonConverter(typeof(StringEnumConverter))]
        public Type condition;

        public Condition() { }

        public Condition(string itemA, Type condition, string itemB = "") {
            this.condition = condition;
            this.valueA = itemA;
            this.valueB = itemB;
        }

        public bool IsValid(Container container) {
            int a = 0;
            if (!int.TryParse(valueA, out a)) {
                a = container[valueA];
            }
            int b = 0;
            if (!int.TryParse(valueB, out b)) {
                b = container[valueB];
            }
#if (DEBUG_LOGIC)
            UnityEngine.Debug.Log(string.Format("{0}({1}) {2} {3}({4})", valueA, a, condition, valueB, b));
#endif
            switch (condition) {
                default:
                    throw new NotImplementedException();
                case Type.have:
                    return (a > 0);
                case Type.equal:
                    return (a == b);
                case Type.nonequal:
                    return (a != b);
                case Type.more:
                    return (a > b);
                case Type.less:
                    return (a < b);
                case Type.emore:
                    return (a >= b);
                case Type.eless:
                    return (a <= b);
            }
        }

        const string HaveTag = "have";
        public string ToCompactString() {
            switch (condition) {
                default:
                    throw new NotImplementedException();
                case Type.have:
                    return String.Format("{0} {1}", HaveTag, valueA);
                case Type.equal:
                    return String.Format("{0} == {1}", valueA, valueB);
                case Type.nonequal:
                    return String.Format("{0} != {1}", valueA, valueB);
                case Type.more:
                    return String.Format("{0} > {1}", valueA, valueB);
                case Type.emore:
                    return String.Format("{0} >= {1}", valueA, valueB);
                case Type.less:
                    return String.Format("{0} < {1}", valueA, valueB);
                case Type.eless:
                    return String.Format("{0} <= {1}", valueA, valueB);
            }
        }

        public static Condition ParseFromCompactString(string value) {
            const string Space = " ";
            var stricted = value.Replace(Space, String.Empty);
            // have itemId
            if (stricted.Contains(HaveTag)) {
                string[] values = stricted.Split(new string[]{ HaveTag }, new StringSplitOptions());
                if (values.Length >= 2) {
                    return new Condition(values[1], Type.have);
                }
            }
            Condition condition = null;
            if (TryParseCondition(stricted, "<>", Type.nonequal, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, "!=", Type.nonequal, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, ">=", Type.emore, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, ">", Type.more, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, "<=", Type.eless, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, "<", Type.less, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, "==", Type.equal, out condition)) {
                return condition;
            }
            if (TryParseCondition(stricted, "=", Type.equal, out condition)) {
                return condition;
            }
            return null;
        }

        private static bool TryParseCondition(string stricted, string conditionString, Type conditionType, out Condition condition) {
            condition = null;
            if (stricted.Contains(conditionString)) {
                string[] values = stricted.Split(new string[] { conditionString }, new StringSplitOptions());
                if (values.Length >= 2) {
                    condition = new Condition(values[0], conditionType, values[1]);
                    return true;
                }
            }
            return false;
        }
    }
}
