#region << Using Directives >>
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using Volpe.Cafe.Data;
using Volpe.Cafe.Settings;
using Volpe.Cafe.Utils;
#endregion
namespace Volpe.Cafe.IO.InputParsers
{
    public class XlParser : Input
    {
        #region 
        protected XlParser(string path, string password, bool postException) : base(path, password)
        {
            this._path = path;
            this._errorList = new StringCollection();
            this._postException = postException;
            try                  { this.ParseInternal(); }
            catch (Exception ex) { this.LogError("Errors were encountered while parsing file: " + ex.Message); }
            finally              { this.Close(); }
            if (this._errorList.Count > 0)
            {
                int maxErrCount = Math.Min(100, this._errorList.Count);
                string err = "\n\nThe input file contains " + this._errorList.Count + " missing or invalid entries.";
                if (this._errorList.Count > maxErrCount) { err += "  (First " + maxErrCount + " errors are shown.)"; }
                err += "\n";
                for (int i = 0; i < maxErrCount; i++)
                {
                    err += ("\n" + this._errorList[i]);
                }
                if (this._postException) { throw new InputException(this._path, err); }
            }
        }
        #endregion
        #region 
        public static Industry ParseMarketData(string path)
        {
            return ParseMarketData(path, string.Empty);
        }
        public static Industry ParseMarketData(string path, string password)
        {
            return new XlMarketDataParser(path, password)._ind;
        }
        public static List<Technology> ParseTechnologies(string path)
        {
            return ParseTechnologies(path, string.Empty);
        }
        public static List<Technology> ParseTechnologies(string path, string password)
        {
            return new XlTechnologiesParser(path, password)._techList;
        }
        public static Parameters ParseParameters(string path)
        {
            return ParseParameters(path, string.Empty);
        }
        public static Parameters ParseParameters(string path, string password)
        {
            return new XlParametersParser(path, password)._value;
        }
        public static List<Scenario> ParseScenarios(string path)
        {
            return ParseScenarios(path, string.Empty);
        }
        public static List<Scenario> ParseScenarios(string path, string password)
        {
            return new XlScenariosParser(path, password)._scenList;
        }
        protected virtual void ParseInternal() { }
        protected void LogError(string message)
        {
            this._errorList.Add(message);
        }
        protected bool VerifyIndexes(string wsName, int[] indexes, string[] names)
        {
            return this.VerifyIndexes(wsName, indexes, names, 0, indexes.Length);
        }
        protected bool VerifyIndexes(string wsName, int[] indexes, string[] names, int startIndex, int length)
        {
            int endIndex = startIndex + length;
            if (indexes.Length != names.Length)
            {
                throw new ArgumentException("The length of the indexes array does not match the length of the names array.", "names");
            }
            if (startIndex < 0 || indexes.Length < endIndex || names.Length < endIndex)
            {
                throw new ArgumentOutOfRangeException("startIndex or length",
                    "The startIndex and/or length is outside the bounds of the indexes and names arrays.");
            }
            bool isValid = true;
            for (int i = startIndex; i < endIndex; i++)
            {
                if (indexes[i] == -1)
                {
                    this.LogError("In the " + wsName + ", " + names[i] + " section or entry not found.");
                    isValid = false;
                }
            }
            return isValid;
        }
        #endregion
        #region 
        public bool HasErrors { get { return this._errorList.Count > 0; } }
        #endregion
        #region 
        string           _path;
        StringCollection _errorList;
        bool             _postException;
        #endregion
    }
}

