#ifndef HGL_IO_DATA_INPUT_STREAM_INCLUDE
#define HGL_IO_DATA_INPUT_STREAM_INCLUDE

#include<hgl/io/InputStream.h>
#include<hgl/type/BaseString.h>
#include<hgl/math/Vector.h>
namespace hgl
{
    namespace io
    {
        class InputStream;

        /**
        * 格式数据输入流基类
        */
        class DataInputStream                                                                       ///格式数据输入流基类
        {
        protected:

            InputStream *in;

        public:

            DataInputStream(InputStream *is)
            {
                in=is;
            }

            virtual ~DataInputStream()
            {
            }

            virtual void Use(InputStream *is)
            {
                in=is;
            }

            virtual int64 Read(void *buf,int64 size)
            {
                if(!buf||size<0)return(-1);

                return(in?in->Read(buf,size):-1);
            }

            virtual int64 Peek(void *buf,int64 size)
            {
                if(!buf||size<0)return(-1);

                return(in?in->Peek(buf,size):-1);
            }

            virtual int64 ReadFully(void *buf,int64 size)
            {
                if(!buf||size<0)return(-1);

                return(in?in->ReadFully(buf,size):-1);
            }

            virtual int64 Seek(int64 offset,SeekOrigin so=SeekOrigin::Begin)
            {
                return(in?in->Seek(offset,so):-1);
            }

            virtual int64   Skip(int64 size)                                                        ///<跳过指定字节不访问
            {
                return(in?in->Skip(size):-1);
            }

            virtual bool    CanRestart  ()const{return in?in->CanRestart():false;}                  ///<是否可以复位
            virtual bool    CanSeek     ()const{return in?in->CanSeek   ():false;}                  ///<是否可以定位
            virtual bool    CanSize     ()const{return in?in->CanSize   ():false;}                  ///<是否可以取得尺寸
            virtual bool    CanPeek     ()const{return in?in->CanPeek   ():false;}                  ///<是否可以预览数据

            virtual bool    Restart     ()const{return in?in->Restart   ():false;}                  ///<复位访问指针
            virtual int64   Tell        ()const{return in?in->Tell      ():-1;}                     ///<返回当前访问位置
            virtual int64   GetSize     ()const{return in?in->GetSize   ():-1;}                     ///<取得流长度
            virtual int64   Available   ()const{return in?in->Available ():-1;}                     ///<剩下的可以不受阻塞读取的字节数

            template<typename T> bool ReadNumber(T &value);

            #define STREAM_READ(type,name)  virtual bool Read##name(type &value)    \
                                            {   \
                                                return Read(value); \
                                            }   \
                                            \
                                            virtual int64 Read##name(type *data,const int64 count)  \
                                            {   \
                                                if(count<=0)return(count);  \
                                                if(!data)return(-1);    \
                                                \
                                                return ReadArrays(data,count);  \
                                            }

            STREAM_READ(char,   Char    );
            STREAM_READ(bool,   Bool    );
            STREAM_READ(int8,   Int8    );
            STREAM_READ(uint8,  Uint8   );

            #undef STREAM_READ

            #define STREAM_READ(type,name)  virtual bool Read##name(type &)=0;  \
                                            virtual int64 Read##name(type *,const int64)=0;

            STREAM_READ(int16,      Int16   );
            STREAM_READ(int32,      Int32   );
            STREAM_READ(int64,      Int64   );

            STREAM_READ(uint16,     Uint16  );
            STREAM_READ(uint32,     Uint32  );
            STREAM_READ(uint64,     Uint64  );

            STREAM_READ(u16char,    UTF16Char);
            STREAM_READ(float,      Float   );
            STREAM_READ(double,     Double  );

            #undef STREAM_READ

            bool Read(Vector2f &vec){return ReadFloat((float *)&vec,2)==2;}
            bool Read(Vector3f &vec){return ReadFloat((float *)&vec,3)==3;}
            bool Read(Vector4f &vec){return ReadFloat((float *)&vec,4)==4;}

            /**
            * 自适应类型数据读取</p>
            * 请在多平台混用的情况下不要使用此函数，以免造成不同平台数据实质结构不一致的情况
            */
            template<typename T> bool Read(T &data)
            {
                return(ReadFully(&data,sizeof(T))==sizeof(T));
            }

            /**
            * 自适应类型数据阵列读取</p>
            * 请在多平台混用的情况下不要使用此函数，以免造成不同平台数据实质结构不一致的情况
            * @param data 数据存放区
            * @param count 数据个数
            * @return 实质读入的数据个数
            * @return <0 出错
            */
            template<typename T> int64 ReadArrays(T *data,int64 count)
            {
                if(count<=0)return(count);
                if(!data)return(-1);

                return ReadFully(data,count*sizeof(T))/sizeof(T);
            }

            /**
            * 自定义类型数据阵列读取</p>
            * 请在多平台混用的情况下不要使用此函数，以免造成不同平台数据实质结构不一致的情况
            * @param count 数据个数
            * @param alloc_count 分配数据个数(默认-1)
            * @return 实质读入的数据指针，请使用delete[]释放
            * @return NULL 出错
            */
            template<typename T> T *ReadArrays(int64 count)
            {
                if(count<=0)return(nullptr);

                T *data=new T[count];

                if(data==0)
                    return(nullptr);

                if(ReadArrays(data,count)!=count)
                {
                    delete[] data;
                    return(nullptr);
                }

                return data;
            }

            virtual bool ReadUTF16LEChars(u16char *,uint);                                          ///<读取utf16-le格式字符阵列到u16char *
            virtual bool ReadUTF16BEChars(u16char *,uint);                                          ///<读取utf16-be格式字符阵列到u16char *

            //32bit str-length
            virtual bool ReadUTF8String         (char *,        uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF8String         (UTF8String &,  uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF8String         (UTF16String &, uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)

            virtual bool ReadUTF16LEString      (u16char *,     uint max_len=0);
            virtual bool ReadUTF16BEString      (u16char *,     uint max_len=0);

            virtual bool ReadUTF16LEString      (UTF16String &, uint max_len=0);                    ///<读取utf16-le格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF16BEString      (UTF16String &, uint max_len=0);                    ///<读取utf16-be格式字符串(前缀四字节的字符串字节长度)

            //16bit str-length
            virtual bool ReadUTF8ShortString    (char *,        uint max_len=0);
            virtual bool ReadUTF8ShortString    (UTF8String &,  uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF8ShortString    (UTF16String &, uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)

            virtual bool ReadUTF16LEShortString (u16char *,     uint max_len=0);
            virtual bool ReadUTF16BEShortString (u16char *,     uint max_len=0);

            virtual bool ReadUTF16LEShortString (UTF16String &, uint max_len=0);                    ///<读取utf16-le格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF16BEShortString (UTF16String &, uint max_len=0);                    ///<读取utf16-be格式字符串(前缀四字节的字符串字节长度)

            //8bit str-length
            virtual bool ReadUTF8TinyString     (char *,        uint max_len=0);
            virtual bool ReadUTF8TinyString     (UTF8String &,  uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF8TinyString     (UTF16String &, uint max_len=0);                    ///<读取utf8格式字符串(前缀四字节的字符串字节长度)

            virtual bool ReadUTF16LETinyString  (u16char *,     uint max_len=0);
            virtual bool ReadUTF16BETinyString  (u16char *,     uint max_len=0);

            virtual bool ReadUTF16LETinyString  (UTF16String &, uint max_len=0);                    ///<读取utf16-le格式字符串(前缀四字节的字符串字节长度)
            virtual bool ReadUTF16BETinyString  (UTF16String &, uint max_len=0);                    ///<读取utf16-be格式字符串(前缀四字节的字符串字节长度)
        };//class DataInputStream

        template<> bool inline DataInputStream::ReadNumber<int8>(int8 &value){return ReadInt8(value);}
        template<> bool inline DataInputStream::ReadNumber<uint8>(uint8 &value){return ReadUint8(value);}

        #define DIS_READ_NUMBER(type,name) template<> bool inline DataInputStream::ReadNumber<type>(type &value){return Read##name(value);}

        DIS_READ_NUMBER(int16,      Int16   );
        DIS_READ_NUMBER(int32,      Int32   );
        DIS_READ_NUMBER(int64,      Int64   );

        DIS_READ_NUMBER(uint16,     Uint16  );
        DIS_READ_NUMBER(uint32,     Uint32  );
        DIS_READ_NUMBER(uint64,     Uint64  );

        DIS_READ_NUMBER(u16char,    UTF16Char);
        DIS_READ_NUMBER(float,      Float   );
        DIS_READ_NUMBER(double,     Double  );

        #undef DIS_READ_NUMBER
    }//namespace io
}//namespace hgl
#include<hgl/io/EndianDataInputStream.h>
#endif//HGL_IO_DATA_INPUT_STREAM_INCLUDE
