using System;
using System.Collections.Generic;
using System.IO;
using Volpe.Cafe;
using Volpe.Cafe.Data;
using Volpe.Cafe.Model;
using Volpe.Cafe.Settings;
using Volpe.Cafe.Utils;
namespace Volpe.Cafe.IO
{
    [Serializable]
    public class LogWriter
    {
        #region 
        LogWriter()
        {
            this._isEmpty = true;
        }
        public LogWriter(string basePath) : this(basePath, true, false) { }
        public LogWriter(string basePath, bool writeCFs, bool writeExtCFs)
        {
            if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); }
            this._basePath    = basePath;
            this._writeCFs    = writeCFs;
            this._writeExtCFs = writeExtCFs;
            this._isEmpty     = false;
        }
        ~LogWriter()
        {
            this.Close();
        }
        #endregion
        #region 
        string GenerateComplianceLogHeader()
        {
            const string header = "LN\tCF\tScen\tMfr\tApplied\tEff\tCost/MPG\tTotal Delta RPE\tTotal Delta Fines\tTotal Delta Credits\tTotal FC Savings\tTotal Affected Sales\t" +
                "Reg-Class\tStandard\tCAFE\tNew CAFE\tFines\tNew Fines\tVeh\tEng\tTrn\tTech-Class\tTechs\tYear\tFE\tShare\tNew FE\tNew Share\t" +
                "Sales\tCost\tPenalty Cost\tImprv\tDelta FE\tDelta Off-Cycle\tDelta CW\tDelta GVWR\tDelta GCWR\tNew FE-2\tImprv-2\tDelta FE-2";
            return header;
        }
        void WriteLog(TextWriter tw, ref string value)
        {
            tw.Write(value);
        }
        public void WriteError(string value)
        {
            if (this._errors != null) { this.WriteLog(this._errors, ref value); }
        }
        public void WriteWarning(string value)
        {
            if (this._warnings != null) { this.WriteLog(this._warnings, ref value); }
        }
        public void WriteSummary(string value)
        {
            if (this._summary != null) { this.WriteLog(this._summary, ref value); }
        }
        public void WriteErrorLine(string value)
        {
            this.WriteError(value); this.WriteError(NewLine);
        }
        public void WriteWarningLine(string value)
        {
            this.WriteWarning(value); this.WriteWarning(NewLine);
        }
        public void WriteSummaryLine(string value)
        {
            this.WriteSummary(value); this.WriteSummary(NewLine);
        }
        public void Open(bool append, int scenCount)
        {
            if (this._basePath == null) { return; }
            this._errors   = new StreamWriter(this._basePath + "\\Errors.txt"  , append);
            this._warnings = new StreamWriter(this._basePath + "\\Warnings.txt", append);
            this._summary  = new StreamWriter(this._basePath + "\\Summary.txt" , append);
            this.OpenCF(append, scenCount);
            this.OpenOther(append, scenCount);
            this._isOpen = true;
        }
        void OpenCF(bool append, int scenCount)
        {
            if (!this._writeCFs) { return; }
            string header = this.GenerateComplianceLogHeader();
            this._cfs = new ComplianceWriter[scenCount];
            for (int i = 0; i < scenCount; i++)
            {
                this._cfs[i] = new ComplianceWriter(this._basePath + "\\cf_trace_sn" + i + ".txt", append);
                this._cfs[i].WriteLine(header);
            }
            if (this._writeExtCFs)
            {
                this._extCFs = new ComplianceWriter[scenCount];
                for (int i = 0; i < scenCount; i++)
                {
                    this._extCFs[i] = new ComplianceWriter(this._basePath + "\\ext-cf_trace_sn" + i + ".txt", append);
                    this._extCFs[i].WriteLine(header);
                }
            }
        }
        protected virtual void OpenOther(bool append, int scenCount) { }
        public void Close()
        {
            if (this._errors   != null) { this.Errors  .Close(); this._errors   = null; }
            if (this._warnings != null) { this.Warnings.Close(); this._warnings = null; }
            if (this._summary  != null) { this.Summary .Close(); this._summary  = null; }
            this.CloseComplianceWriters(this._cfs);
            this.CloseComplianceWriters(this._extCFs);
            this.CloseOther();
            this._isOpen = false;
        }
        protected void CloseComplianceWriters(ComplianceWriter[] writers)
        {
            if (writers != null)
            {
                for (int i = 0; i < writers.Length; i++)
                {
                    if (writers[i] != null) { writers[i].Close(); writers[i] = null; }
                }
            }
        }
        protected virtual void CloseOther() { }
        #endregion
        #region 
        public string LogPath
        {
            get { return this._basePath; }
            set
            {
                if (this._isEmpty) { throw new InvalidOperationException("Cannot modify an empty LogWriter--it is read-only."); }
                if (this._isOpen)  { throw new InvalidOperationException("The LogWriter is opened; path cannot be modified."); }
                this._basePath = value;
            }
        }
        public bool WriteCFs { get { return this._writeCFs; } }
        public bool WriteExtCFs { get { return this._writeExtCFs; } }
        public bool IsEmpty { get { return this._isEmpty; } }
        public bool IsOpen { get { return this._isOpen; } }
        public TextWriter Errors { get { return this._errors;   } }
        public TextWriter Warnings { get { return this._warnings; } }
        public TextWriter Summary { get { return this._summary;  } }
        public ComplianceWriter[] CFs { get { return this._cfs; } }
        public ComplianceWriter[] ExtCFs { get { return this._extCFs; } }
        #endregion
        #region 
        public static readonly LogWriter Empty = new LogWriter();
        public static readonly string NewLine = "\n";
        string _basePath;
        bool   _writeCFs;
        bool   _writeExtCFs;
        bool   _isEmpty;
        bool   _isOpen;
        TextWriter _errors;
        TextWriter _warnings;
        TextWriter _summary;
        ComplianceWriter[] _cfs;
        ComplianceWriter[] _extCFs;
        #endregion
    }
}

