/*
 * TextMemoryStream.cs
 * Copyright (c) 2008-2009 kbinani
 *
 * This file is part of Boare.Lib.Vsq.
 *
 * Boare.Lib.Vsq is free software; you can redistribute it and/or
 * modify it under the terms of the BSD License.
 *
 * Boare.Lib.Vsq is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace Boare.Lib.Vsq {

    /// <summary>
    /// メモリー上でテキストファイルを扱うためのクラス．
    /// </summary>
    public class TextMemoryStream : IDisposable {
        FileAccess m_access;
        MemoryStream m_ms = null;
        Encoding m_enc;
        byte[] NEW_LINE;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        public void write( string value ) {
            byte[] buff = m_enc.GetBytes( value );
            m_ms.Write( buff, 0, buff.Length );
        }

        public void rewind() {
            m_ms.Seek( 0, SeekOrigin.Begin );
        }

        public void writeLine( string s ) {
            byte[] buff = m_enc.GetBytes( s + Environment.NewLine );
            m_ms.Write( buff, 0, buff.Length );
        }

        public void close() {
            if ( m_ms != null ) {
                m_ms.Close();
            }
        }

        public int peek() {
            long current = m_ms.Position;
            int ret = m_ms.ReadByte();
            m_ms.Seek( current, SeekOrigin.Begin );
            return ret;
        }

        public string readLine() {
            List<byte> buffer = new List<byte>();
            byte value;
            int ret;
            ret = m_ms.ReadByte();
            while ( ret >= 0 ) {
                value = (byte)ret;
                if ( value == NEW_LINE[0] ) {
                    byte next;
                    long current = m_ms.Position; //0x0Dを検出した直後のストリームの位置
                    for ( int i = 1; i < NEW_LINE.Length; i++ ) {
                        ret = m_ms.ReadByte();
                        if ( ret >= 0 ) {
                            next = (byte)ret;
                            if ( next != NEW_LINE[i] ) {
                                m_ms.Seek( current, SeekOrigin.Begin );
                                break;
                            }
                        }
                    }
                    break;
                }
                buffer.Add( value );
                ret = m_ms.ReadByte();
            }
            return Encoding.Unicode.GetString( buffer.ToArray() );
        }

        public void Dispose() {
            if ( m_ms != null ) {
                m_ms.Close();
            }
        }

        public TextMemoryStream( string path, Encoding encode ) {
            m_access = FileAccess.Read;
            m_ms = new MemoryStream();
            m_enc = encode;
            if ( File.Exists( path ) ) {
                using ( StreamReader sr = new StreamReader( path, encode ) ) {
                    while ( sr.Peek() >= 0 ) {
                        string line = sr.ReadLine();
                        byte[] buffer = m_enc.GetBytes( line + Environment.NewLine );
                        m_ms.Write( buffer, 0, buffer.Length );
                    }
                }
                m_ms.Seek( 0, SeekOrigin.Begin );
            }
            NEW_LINE = m_enc.GetBytes( Environment.NewLine );
        }

        public TextMemoryStream( FileAccess access ) {
            m_access = access;
            m_ms = new MemoryStream();
            m_enc = Encoding.Unicode;
            NEW_LINE = m_enc.GetBytes( Environment.NewLine );
        }

        public TextMemoryStream() {
            m_access = FileAccess.Write;
            m_ms = new MemoryStream();
            m_enc = Encoding.Unicode;
            NEW_LINE = m_enc.GetBytes( Environment.NewLine );
        }
    }

}
