
#ifndef DKUTIL_CRYPTOGRAPH_BUFFER_HPP
#define DKUTIL_CRYPTOGRAPH_BUFFER_HPP

#include <dkutil/cryptograph/arcfour.hpp>
#include <dkutil/cryptograph/blowfish.hpp>
#include <dkutil/cryptograph/hc256.hpp>
#include <dkutil/cryptograph/snow2.hpp>
#include <dkutil/detail/convert_interface.hpp>
//#include <dkutil/buffer.hpp>

namespace dkutil{

/**
暗号化して保存するバッファ
*/
template<class POLICY_T>
class CStreamCipherBuffer{
public:
	typedef typename POLICY_T policy_type;
	typedef typename size_t size_type;
	typedef typename sptr<IStreamCipherConvert> cipher_ptr;
protected:
	cipher_ptr mObj;
	typedef typename sptr<CReservePassword> password_ptr;
	password_ptr mPass;
	shared_buffer mBuff;
	bool mCopied;

	///@return 両方とも無効だったらtrue
	bool object_null()const{
		return mPass.isNull() || mObj.isNull();
	}
public:
	CStreamCipherBuffer(){
		clear();
	}
	CStreamCipherBuffer(const CPasswordOption &x){
		reset(x);

	}
	~CStreamCipherBuffer(){}
	void clear(){
		mCopied = false;
		mBuff.clear();
		mObj.clear();
		mPass.clear();
	}
	bool reset(const CPasswordOption &x){
		clear();

		/*mObj.reset(new policy_type(x));
		if(mObj.isNULL()){
			return false;
		}*/
		mPass.reset(new CReservePassword(x));
		if(mPass.isNull()){
			mObj.clear();
			return false;
		}
		return true;
	}
	///暗号化オブジェクトのステートを元に戻す
	bool password_reset(){
		if(mPass.isNull())
			return false;
		
		CPasswordOption x = mPass->getPassword();
		mObj.reset(new policy_type(x));
		
		return true;
	}
	///@return reset()済みかどうか
	bool isValid()const{
		return mPass.isNull()==false;
	}
	///バッファ内に暗号化して保存する
	bool copy(const void *p,size_type size){
		synchronized guard;
		/*if(false==mCopied){
			return false;
		}*/
		DKUTIL_RETURN_FALSE(password_reset());
		DKUTIL_RETURN_FALSE(mBuff.copy((const uint8 *)p,size));
		
		mObj->convert(mBuff.get(),mBuff.size());
		mCopied = true;
		return true;
	}
	///バッファ内のデータを複合化してデータを取得する。
	bool get_buffer(shared_buffer &x){
		synchronized guard;
		if(false==mCopied){
			return false;
		}
		x = mBuff;
		DKUTIL_RETURN_FALSE(password_reset());
		mObj->convert(x.get(),x.size());
		return true;
	}

};


}//end of dkutil namespace





#endif