using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace nft.core.view
{    
    public class ConditionedResource<T>
    {
        internal protected T Default;

        public ConditionedResource(T _default) {
            this.Default = _default;
        }

        public T this[ISceneParams p] {
            get {
                T result = this.Default;
                Choose(p, ref result);
                return result;
            }
        }

        internal protected virtual bool Choose(ISceneParams p, ref T res){
            res = Default;
            return true;
        }

        public override string ToString() {
            return GetType().Name;
        }
    }

    internal class SingleConditionResouce<T> : ConditionedResource<T>
    {
        protected readonly ISceneCondition Condition;
        internal SingleConditionResouce(ISceneCondition cond, T val) :base(val){
            this.Condition = cond;
        }

        internal protected override bool Choose(ISceneParams p, ref T res) {
            if (Condition.IsMatch(p)) {
                res = Default;
                return true;
            } else {
                return false;
            }
        }

        public override string ToString() {
            return String.Format("{0}[when={1}]", GetType().Name, Condition);
        }
    }

    internal class NestedConditionsResouceRoot<T> : ConditionedResource<T>
    {
        internal protected readonly List<ConditionedResource<T>> children;
        internal NestedConditionsResouceRoot(T val)
            : base(val) {
            this.children = new List<ConditionedResource<T>>();
        }

        internal protected override bool Choose(ISceneParams p, ref T res) {
            foreach (ConditionedResource<T> cc in children) {
                //Debug.WriteLine("  enter "+ cc);
                if (cc.Choose(p, ref res)) {
                    return true;
                }
            }
            res = Default;
            return true;
        }

        public void AddChild(ConditionedResource<T> child) {
            children.Add(child);
        }

        public override string ToString() {
            return String.Format("{0}", GetType().Name);
        }
    }

    internal class NestedConditionsResouce<T> : NestedConditionsResouceRoot<T>
    {
        internal protected readonly ISceneCondition Condition;
        internal NestedConditionsResouce(ISceneCondition cond, T val)
            : base(val) {
            this.Condition = cond;
        }

        internal protected override bool Choose(ISceneParams p, ref T res) {
            if (Condition.IsMatch(p)) {                
                return base.Choose(p, ref res);
            } else {
                return false;
            }
        }

        public override string ToString() {
            return String.Format("{0}[when={1}]", GetType().Name, Condition);
        }
    }
}
