namespace CsvReadWrite
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Linq;
    


    public static class StreamReaderExtention
    {
         public static string ReadLine(this StreamReader sr, string delimiter)
         {
             var sb = new StringBuilder();
             var buf = new char[1];
             var chars = new StringBuilder();
             var isLineEnd = false;

             do
             {
                 sr.Read(buf, 0, 1);
                 sb.Append(buf);
                 chars.Append(buf);

                string testchar = chars.ToString();
                char buf2 = buf[0];

                int cnts = testchar.Length;
                char buf3 = buf2;


                 if (!delimiter.StartsWith(chars.ToString()))
                 {
                     chars = new StringBuilder();//.Clear();
                 }
                 else
                 {
                     if (delimiter == chars.ToString())
                        isLineEnd = true;
                 }

             } while (!sr.EndOfStream && !isLineEnd);

            if(sb.Length <= 1)
            {
                return null;
            }

            if (isLineEnd)
            {
                sb = sb.Remove(sb.Length - delimiter.Length, delimiter.Length);
            }

             return sb.ToString();
         }
     }

      /*  public static String ReadUntil(this StreamReader streamReader, String delimiter)
        {
            StringBuilder stringBuilder = new StringBuilder();

            while (!streamReader.EndOfStream)
            {
                stringBuilder.Append(value: (Char)streamReader.Read());

                if (stringBuilder.ToString().EndsWith(value: delimiter))
                {
                    stringBuilder.Remove(stringBuilder.Length - delimiter.Length, delimiter.Length);
                    break;
                }
            }

            return stringBuilder.ToString();
        }
        */
    ///}


    /// <summary>
    /// CSV形式のストリームを読み込む CsvReader を実装します。
    /// </summary>
    public class CsvReader : IDisposable
    {

        /// <summary>
        /// 現在読み込んでいるフィールドがダブルクォートで囲まれたフィールドかどうか
        /// </summary>
        private bool isQuotedField = false;

        /// <summary>
        /// CSVを読み込むストリーム
        /// </summary>
        private StreamReader stream = null;

        /// <summary>
        /// ファイル名を指定して、 <see cref="CsvReader">CsvReader</see> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="path">読み込まれる完全なファイルパス。</param>
        public CsvReader(string path) :
            this(path, Encoding.Default)
        {
        }

        /// <summary>
        /// ファイル名、文字エンコーディングを指定して、 <see cref="CsvReader">CsvReader</see> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="path">読み込まれる完全なファイルパス。</param>
        /// <param name="encoding">使用する文字エンコーディング。</param>
        public CsvReader(string path, Encoding encoding)
        {
            var file = new FileStream(path, FileMode.Open, FileAccess.Read);
            this.stream = new StreamReader(file, encoding);
        }

        /// <summary>
        /// ストリームを指定して、 <see cref="CsvReader">CsvReader</see> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="stream">読み込まれるストリーム。</param>
        public CsvReader(Stream stream)
        {
            this.stream = new StreamReader(stream);
        }

        /// <summary>
        /// 文字列データを指定して、 <see cref="CsvReader">CsvReader</see> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="data">文字列データ。</param>
        public CsvReader(StringBuilder data)
        {
            var buffer = Encoding.Unicode.GetBytes(data.ToString());
            var memory = new MemoryStream(buffer);
            this.stream = new StreamReader(memory);
        }

        /// <summary>
        /// CsvReader オブジェクトと、その基になるストリームを閉じ、
        /// リーダーに関連付けられたすべてのシステムリソースを解放します。
        /// </summary>
        public void Close()
        {
            if (this.stream == null)
            {
                return;
            }

            this.stream.Close();
        }

        /// <summary>
        /// この CsvReader オブジェクトによって使用されているすべてのリソースを解放します。
        /// </summary>
        public void Dispose()
        {
            if (this.stream == null)
            {
                return;
            }

            this.stream.Close();
            this.stream.Dispose();
            this.stream = null;
        }

        /// <summary>
        /// Reads a record of characters from the current stream and returns that data as a character array.
        /// </summary>
        /// <returns>The next record from the input stream. Return null if it reached the end of the input stream</returns>
        public List<string> ReadRow()
        {
            var file = this.stream;
            var line = string.Empty;
            
            var field = new StringBuilder();

            //while ((line = file.ReadLine("\n")) != null)
            if ((line = file.ReadLine()) != null)
            {
                var record = new List<string>();
                foreach (var col in line.Split(",".ToCharArray()))
                {
                    string tmp = col.Trim("\"'".ToCharArray());
                    record.Add(tmp);
                }

                return record;
            } else
                return null;
        }

       

        /// <summary>
        /// すべての文字の現在位置から末尾までを読み込みます。
        /// </summary>
        /// <returns>
        /// ストリームの現在位置から末尾までのストリームの残り部分。
        /// 現在の位置がストリームの末尾である場合は、空の配列が返されます。
        /// </returns>
        public List<List<string>> ReadToEnd()
        {
            var data = new List<List<string>>();
            var record = new List<string>();

            while ((record = this.ReadRow()) != null)
            {
                data.Add(record);
            }

            return data;
        }

       
    }
}