#region << Using Directives >>
using System;
using System.IO;
using System.Text;
using Volpe.Cafe.Model;
using Volpe.Cafe.Settings;
#endregion
namespace Volpe.Cafe.IO.Reporting.CSV
{
    [Serializable]
    public abstract class DelimitedReportingBase
    {
        #region 
        public DelimitedReportingBase(string path, bool append, char delimiter)
        {
            this._disposed        = false;
            this._path            = path;
            this._stream          = new StreamWriter(path, append);
            this._newLine         = this._stream.NewLine.ToCharArray();
            this._delimiter       = delimiter;
            this._delimiterString = delimiter.ToString();
            this._buffer          = new StringBuilder(4096);
            if (!append) { this._stream.Write(this.GetHeader()); }
        }
        #endregion
        #region 
        protected abstract string GetHeader();
        public void ParseData(Scenario scen, ModelYear year, ICompliance compliance)
        {
            try   { this.ParseData_Internal(scen, year, compliance); }
            catch { this.Close(); }
        }
        protected abstract void ParseData_Internal(Scenario scen, ModelYear year, ICompliance compliance);
        protected void Write(object value)
        {
            if (value == null) { this.Write(string.Empty); }
            else               { this.Write(value.ToString()); }
        }
        protected void Write(bool value)
        {
            this.Write(value.ToString());
        }
        protected void Write(decimal value)
        {
            this.Write(value.ToString());
        }
        protected void Write(double value)
        {
            this.Write(value.ToString());
        }
        protected void Write(float value)
        {
            this.Write(value.ToString());
        }
        protected void Write(long value)
        {
            this.Write(value.ToString());
        }
        protected void Write(int value)
        {
            this.Write(value.ToString());
        }
        protected void Write(short value)
        {
            this.Write(value.ToString());
        }
        protected void Write(byte value)
        {
            this.Write(value.ToString());
        }
        protected void Write(sbyte value)
        {
            this.Write(value.ToString());
        }
        protected void Write(ulong value)
        {
            this.Write(value.ToString());
        }
        protected void Write(uint value)
        {
            this.Write(value.ToString());
        }
        protected void Write(ushort value)
        {
            this.Write(value.ToString());
        }
        protected void Write(char value)
        {
            this.Write(value.ToString());
        }
        protected void Write(string value)
        {
            if (value != null)
            {
                if (value.Contains("\""))
                {
                    value = "\"" + value.Replace("\"", "\"\"") + "\"";
                }
                else if (value.Contains(this._delimiterString) || value.Contains("\r") || value.Contains("\n"))
                {
                    value = "\"" + value + "\"";
                }
            }
            this._buffer.Append(value);
            this._buffer.Append(this._delimiter);
        }
        protected void WriteEmpty(int count)
        {
            for (int i = 0; i < count; i++)
            {
                this._buffer.Append(this._delimiter);
            }
        }
        protected void NewRow()
        {
            if (this._buffer.Length != 0)
            {
                this._stream.WriteLine();
                this._stream.Write(this._buffer.ToString(0, this._buffer.Length - 1));
                this._buffer.Length = 0;
            }
        }
        public void Close()
        {
            this.NewRow();
            this._stream.Close();
            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); } }
        public abstract string ReportName { get; }
        public char Delimiter { get { return this._delimiter; } }
        #endregion
        #region 
        bool          _disposed;     
        string        _path;
        StreamWriter  _stream;
        char[]        _newLine;
        char          _delimiter;
        string        _delimiterString;
        StringBuilder _buffer;
        #endregion
    }
}

