#region << Using Directives >>
using System;
using System.IO;
using Volpe.Cafe.Data;
using Volpe.Cafe.Model;
using Volpe.Cafe.Settings;
using Volpe.Cafe.Utils;
using Volpe.XlLib;
#endregion
namespace Volpe.Cafe.IO.Reporting.XL
{
    [Serializable]
    public class XlReportGenerator
    {
        #region 
        XlReportGenerator()
        {
            this._isEmpty = true;
        }
        public XlReportGenerator(ICompliance compliance)
        {
            this._compliance = compliance;
            this._compliance.ScenarioCompleted += new ModelingProgressEventHandler(this.Compliance_ScenarioCompleted);
            this._compliance.ModelingCompleted += new ModelingEventHandler(this.Compliance_ModelingStoppedOrCompleted);
            this._compliance.ModelingStopped   += new ModelingEventHandler(this.Compliance_ModelingStoppedOrCompleted);
            this._isEmpty = false;
            this._minYear = compliance.Data.MinYear.Year;
            this._maxYear = compliance.Data.MaxYear.Year;
        }
        #endregion
        #region 
        void Compliance_ModelingStoppedOrCompleted(object sender, ModelingEventArgs e)
        {
            this._compliance.ScenarioCompleted -= new ModelingProgressEventHandler(this.Compliance_ScenarioCompleted);
            this._compliance.ModelingCompleted -= new ModelingEventHandler(this.Compliance_ModelingStoppedOrCompleted);
            this._compliance.ModelingStopped   -= new ModelingEventHandler(this.Compliance_ModelingStoppedOrCompleted);
        }
        void Compliance_ScenarioCompleted(object sender, ModelingProgressEventArgs e)
        {
            this.GenerateReportsForScenario((e.Progress == null) ? null : e.Progress.Scenario);
        }
        protected void GenerateReportsForScenario(Scenario scen)
        {
            if (scen == null || this.IsModelStopped()) { return; }
            try
            {
                this._reporting = true;
                this._reportingProgress = "Initializing reports ...";
                this.OpenReports(scen.Index);   
                if (!this.IsModelStopped())
                {   
                    Industry[] scenData = this._compliance.GetData(scen);
                    Industry[] baseData = (scen.Index == 0) ? scenData : this._compliance.GetData(this._compliance.Settings.Scenarios[0]);
                    Industry   ppData   = this._compliance.Data;
                    for (int i = 0; i < this._compliance.ModelYears.Length; i++)
                    {
                        if (this.IsModelStopped()) { break; }
                        ModelYear year = this._compliance.ModelYears[i];
                        this.WriteReportData(scen, year, scenData[year.Index], baseData[year.Index], ppData);
                    } 
                }
            }
            catch (OutputException ex) { throw ex; }
            catch (Exception       ex) { throw new OutputException("<unknown file>", null, ex); }
            finally
            {
                this.CloseReports(scen.Index);  
                this._reportingProgress = "Reporting for scenario " + scen.Index + " completed.";
                this._reporting = false;
            }
        }
        protected virtual void OpenReports(int snIndex) { }
        protected virtual void WriteReportData(Scenario scen, ModelYear year, Industry scenData, Industry baseData, Industry ppData) { }
        protected virtual void CloseReports(int snIndex) { }
        protected void CloseReport(XlReportingBase report)
        {
            if (report != null && !report.Disposed)
            {
                this.UpdateProgress("Saving " + report.FileName + " report.");
                bool saveReport = !this.IsModelStopped();
                report.Close(saveReport);
                if (!saveReport) { File.Delete(report.Path); }
            }
        }
        protected void UpdateProgress(string progress)
        {
            this._reportingProgress = progress;
        }
        protected bool IsModelStopped()
        {
            return (this._compliance.Stopped || this._compliance.State == ModelingState.StopRequested);
        }
        #endregion
        #region 
        public bool Reporting { get { return !this._isEmpty && this._reporting; } }
        public string ReportingProgress { get { return this._reportingProgress; } }
        protected ICompliance Compliance { get { return this._compliance; } }
        protected string OutputPath { get { return this._compliance.Settings.OutputSettings.OutputPath + "\\reports-xls"; } }
        #endregion
        #region 
        public static readonly XlReportGenerator Empty = new XlReportGenerator();
        ICompliance _compliance;
        bool   _isEmpty;
        bool   _reporting;
        string _reportingProgress;
        int _minYear;
        int _maxYear;
        #endregion
    }
}

