
#ifndef DKUTIL_DETAIL_STREAM_CODING_INTERFACE_HPP
#define DKUTIL_DETAIL_STREAM_CODING_INTERFACE_HPP

#include <dkutil/macro.hpp>
#include <dkutil/config.hpp>
#include <dkutil/scoped_buffer.hpp>
#include <dkutil/detail/serialize_interface.hpp>
#include <stdio.h>

namespace dkutil{


template<class SECOND_HEADER_T>
class stream_coding_interface : public read_convert_block<SECOND_HEADER_T>{
	
	
};
class IStreamCoding{
private:
	///戻り値
	int mResult;
	///識別子
	uint32 mSig;

protected:
	
	void setResult(int r){
		mResult = r;
	}
	void setSignature(uint32 a){
		mSig = a;
	}
	ISerializeStream *mP;
public:
	typedef IStreamCoding self_type ;

	
	virtual ~IStreamCoding(){}
	virtual bool reset(uint32 signature_,ISerializeStream *p)
	{
		setSignature(signature_);
		mP = p;
	}
	///複合化する。@return edkResultのどれか
	virtual int decode(const BYTE *src,size_t size,BYTE *dest,size_t destsize) = 0;
	///暗号化する。@return edkResultのどれか
	virtual int encode(const BYTE *src,size_t size,BYTE *dest,size_t destsize) = 0;

	//decodeしたらのサイズ
	//virtual size_t decoded_size(const BYTE *src,size_t size)const = 0;
	
	///エンコード後のサイズ
	virtual size_t getEncodedSize()const = 0;
	
	///エンコード時の出力予定のサイズ (普通より大きめの値を返されます。) 
	virtual size_t getEncodeOutputSize(size_t size)const = 0;
	/**
	@param pData[in] デコードする予定のデータ
	@param size[in] デコードする予定のサイズ
	@throw アクセス不可な所へアクセスしようとすると std::runtime_errorをぷっぱなす。
	*/
	///デコード時の出力予定のサイズ　
	virtual size_t getDecodeOutputSize()const = 0;

	///デコード後の有効なデータのサイズを返す
	virtual size_t getDecodeValidOutputSize()const = 0;
	///シグネチャ
	ULONG getSignature()const{
		return mSig;
	}

	///@return encode decodeの戻り値を返す
	int getResult()const{
		return mResult;
	}

	///encode または decodeが成功したらTRUE
	bool isSucceeded()const{
		return DKUTIL_SUCCEEDED_BOOL(mResult);
	}
	///@return バッファがオーバーフローしたようならTRUE
	bool is_bufferoverflow()const{
		return edk_BufferOverFlow==mResult;
	}
	///@return 圧縮する、暗号化する、等の価値が無かったらTRUE
	bool is_valueless()const{
		return edk_NoValueToProcess==mResult;
	}

	/*!
	@throw 致命的なエラーの場合、std::runtime_errorを投げる
	*/
	template<class BUFFER_T>
	bool encode(const BYTE *src,size_t srcsize,BUFFER_T &buff)
	{
		size_t size = getEncodeOutputSize(srcsize);
		//バッファの先頭にヘッダファイルを入れる。
		if(buff.size() < size){
			//buff.resize(size);
			buff.reserve(size);
		}
		int r = encode(src,srcsize,buff.get(),buff.size());

		return DKUTIL_SUCCEEDED_BOOL(r);
	}
	template<class BUFFER_T>
	bool decode(const BYTE *src,size_t srcsize,BUFFER_T &buff){
		int r = edk_FAILED;
		size_t size = getDecodeOutputSize(src,srcsize);
		/*if(0==size){
			DKUTIL_THROW_OR_NOTICE(std::runtime_error("
		}*/

		if(size > buff.size())
		{//バッファが足らなかったら。
			//リサイズ
			//buff.resize(size);
			buff.reserve(size);
		}		
		
		return DKUTIL_SUCCEEDED_BOOL(decode(src,srcsize,buff.get(),buff.size()));
	}
	/*
	int encode(const BYTE *src,size_t size,IStream *dest_s){
		if(dest_s->type() != 	memory_stream_type){
			return edk_ArgumentException;
		}
		return encode(src,size,(unsigned char *)dest_s->data(),dest_s->size());
	}

	int decode(const BYTE *src,size_t size,IStream *dest_s){
		if(dest_s->type() != memory_stream_type){
			return edk_ArgumentException;
		}
		return decode(src,size,(unsigned char *)dest_s->data(),dest_s->size());
	}
	*/
	int encode(const BYTE *src,size_t size,IMemoryStream *dest_s){
	
		return encode(src,size,(unsigned char *)dest_s->data(),dest_s->size());
	}

	int decode(const BYTE *src,size_t size,IMemoryStream *dest_s){
		
		return decode(src,size,(unsigned char *)dest_s->data(),dest_s->size());
	}
};



}//end of dkutil namespace



#endif