#region << Using Directives >>
using System;
using System.IO;
using Volpe.Cafe.Data;
using Volpe.Cafe.Settings;
using Volpe.XlLib;
#endregion
namespace Volpe.Cafe.IO.Reporting.XL
{
    [Serializable]
    public abstract class XlReportingBase
	{
        #region 
        public XlReportingBase(string path, OutputSettings outputSettings, XlUtilities templateFile, string templateName)
        {
            this.InitReport(path, outputSettings);
            this.InitTemplate(templateFile, templateName);
            this._wsOpen   = false;
            this._wsCount  = 0;
            this._disposed = false;
        }
        #endregion
        #region 
        void InitReport(string path, OutputSettings outputSettings)
        {
            if (File.Exists(path)) { File.Delete(path); }
            this._xlu = new XlUtilities(path, false, null, null, XlCryptoSettings.Empty);
            this._path = path;
        }
        void InitTemplate(XlUtilities templateFile, string templateName)
        {
            this._templateFile = templateFile;
            this._templateName = templateName;
            object[,] tBuf = templateFile.GetData(templateName, true);
            this._tRows = tBuf.GetUpperBound(0);
            this._tCols = tBuf.GetUpperBound(1);
            this._template = new object[this._tRows, this._tCols];
            for (int i = 0; i < this._tRows; i++)
            {
                for (int j = 0; j < this._tCols; j++)
                {   
                    this._template[i, j] = tBuf[i + 1, j + 1];
                }
            }
        }
        public void ParseData(Scenario scen, ModelYear year, Industry scenData, Industry baseData, Industry ppData)
        {
            try
            {
                this.ParseData_Internal(scen, year, scenData, baseData, ppData);
            }
            catch (Exception ex)
            {
                if (this._wsOpen) { this.CloseBuffer(); }
                this.Close(false);
                throw new OutputException(this.FileName, null, ex);
            }
        }
        protected abstract void ParseData_Internal(Scenario scen, ModelYear year, Industry scenData, Industry baseData, Industry ppData);
        public void OpenBuffer(string bufName)
        {
            this.OpenBuffer(bufName, true);
        }
        public void OpenBuffer(string bufName, bool copyTemplateData)
        {
            this.OpenBufferInternal(bufName, false, XlSize.Empty, copyTemplateData);
        }
        public void OpenBuffer(string bufName, XlSize size)
        {
            this.OpenBuffer(bufName, size, true);
        }
        public void OpenBuffer(string bufName, XlSize size, bool copyTemplateData)
        {
            this.OpenBufferInternal(bufName, true, size, copyTemplateData);
        }
        void OpenBufferInternal(string bufName, bool useCustomSize, XlSize customSize, bool copyTemplateData)
        {
            if (this._disposed) { throw new XlReportingException("The report was already closed.", this._path); }
            if (this._wsOpen) { throw new XlReportingException("A buffer was already opened for output.", this._path); }
            this._wsOpen = true;
            this._bRows = (useCustomSize) ? Math.Max(customSize.Rows   , this._tRows) : this._tRows;
            this._bCols = (useCustomSize) ? Math.Max(customSize.Columns, this._tCols) : this._tCols;
            this._buffer = new object[this._bRows, this._bCols];
            if (copyTemplateData)
            {
                if (useCustomSize)
                {
                    for (int i = 0; i < this._tRows; i++)
                    {
                        for (int j = 0; j < this._tCols; j++)
                        {
                            this._buffer[i, j] = this._template[i, j];
                        }
                    }
                }
                else
                {
                    Array.Copy(this._template, this._buffer, this._template.Length);
                }
            }
            if (this._wsCount == 0) { this._xlu.DeleteAllWorksheets(); }    
            this._xlu.CopyWorksheet(this._templateFile, this._templateName, ++this._wsCount);
            this._xlu.SetWorksheetName(this._wsCount, bufName);
            if (this._wsCount == 1) { this._xlu.DeleteWorksheet(2); }       
        }
        public void CloseBuffer()
        {
            this.CloseBuffer(true, new XlRange(1, 1, this._bRows, this._bCols));
        }
        public void CloseBuffer(bool autoFitText, XlRange autoFitRange)
        {
            if (this._disposed) { throw new XlReportingException("The report was already closed.", this._path); }
            if (!this._wsOpen) { throw new XlReportingException("A buffer has not been opened for output.", this._path); }
            this._xlu.SetData(this._wsCount, this._buffer);
            if (autoFitText)
            {
                this._xlu.AutoFitText(autoFitRange.Cell1, autoFitRange.Cell2);
            }
            this._wsOpen = false;
        }
        public void Close(bool saveChanges)
        {
            if (this._disposed) { throw new XlReportingException("The report was already closed.", this._path); }
            if (this._wsOpen) { throw new XlReportingException("All output buffers must be closed before saving the report.", this._path); }
            this._xlu.ActivateWorksheet(1);
            this._xlu.Close(saveChanges);
            this._disposed = true;
        }
        #endregion
        #region 
        public bool Disposed { get { return this._disposed; } }
        public string Path { get { return this._path; } }
        public string FileName { get { return System.IO.Path.GetFileName(this._path); } }
        protected int Rows { get { return this._bRows; } }
        protected int Cols { get { return this._bCols; } }
        protected bool WSOpen { get { return this._wsOpen; } }
        #endregion
        #region 
        XlUtilities _templateFile;
        string      _templateName;
        object[,]   _template;
        int         _bRows, _bCols, _tRows, _tCols;     
        string _path;
        XlUtilities _xlu;
        protected object[,] _buffer;
        bool _wsOpen;
        int  _wsCount;
        bool _disposed;     
        #endregion
	}
}

