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

namespace nft.framework.loader
{
    public interface IParamsParser
    {
        /// <summary>
        /// full text which current loader contains.
        /// returns original text source even if their can be parsed as chilren.
        /// </summary>
        string InnerText { get; }
        
        /// <summary>
        /// true if current loader is empty.
        /// </summary>
        bool IsNull { get; }

        /// <summary>
        /// Enumelate all children with it's key.
        /// </summary>
        /// <returns></returns>
        IEnumerator<KeyValuePair<String,IParamsParser>> EnumChildren();

        /// <summary>
        /// Enumelate all children which corresnpond to specified key.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        IEnumerator<IParamsParser> EnumChildren(string key);

        /// <summary>
        /// Resolve offset file path and returns as IFileSource.
        /// returns null if corresponding file does not found.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        IFileSource GetFileSource(string path);
    }
    
    public sealed class NullParam : IParamsParser {
        public static NullParam TheInstance = new NullParam();

        NullParam() { }
        
        public string InnerText {
            get { return null; }
        }

        public bool IsNull {
            get { return true; }
        }

        public IEnumerator<KeyValuePair<String, IParamsParser>> EnumChildren() {
            yield break;
        }

        public IEnumerator<IParamsParser> EnumChildren(string key) {
            yield break;
        }

        public IFileSource GetFileSource(string path) {
            return null;
        }
    }

    public class PlainStringParam : IParamsParser
    {
        private readonly string text;
        private readonly IParamsParser owner;
        public PlainStringParam(string s, IParamsParser owner) {
            this.text = s;
            this.owner = owner;
        }

        public PlainStringParam(string s) :this(s, null){
        }

        public string InnerText {
            get { return text; }
        }

        public bool IsNull {
            get { return false; }
        }

        public IEnumerator<KeyValuePair<String, IParamsParser>> EnumChildren() {
            yield break;
        }

        public IEnumerator<IParamsParser> EnumChildren(string key) {
            yield break;
        }

        public IFileSource GetFileSource(string path) {
            if (owner != null) {
                return owner.GetFileSource(path);
            } else {
                return null;
            }
        }
    }
}
