#ifndef __LCF_RNN_H_
#define __LCF_RNN_H_
#include "tensor.h"
#include "tensorOperate.h"
#include "fbaGroupLayer.h"
#include "linearLayer.h"
#include "fullConnectLayer.h"
#include "formatToLayer.h"
#include "activeLayer.h"
#include "biasLayer.h"
#include "fusionLayer.h"

#define MYFC FCLayer
//#define MYFC FBAGroupLayer

class RNNLayer : public TensorOperate
{
    public:
        RNNLayer();
        virtual ~RNNLayer();
        void RealeaseMemory();
        void SetLayerConfig(int ifType, int iID, int iMaxSeqNum, DevicesBatchDisptach *iDevicesBatchDisptach, int iHNum, int iHDim, int iInDim, \
                            float iLambda, float iAlpha, float lb, float ld, int ls, int ifHaveInX, int ifOutResult);
        void CompuateOutY(int devID, int seqNum);
        void CompuateOutD(int devID, int seqNum);
        void UpdateWeightMain();
        void SaveLayerWeight(int n);
        void LoadLayerWeight();
        int GetHidVecDim();
 
        void ComputeAndCreateOutYInDTensorInfo();
        void CreateParaAndInstance();
                
        void SetSTInitData(int devID, MemoryHandle *initData);
        
        void ComputerYMemRealease(int devID);
        void ComputerDMemRealease(int devID);

        FormatToLayer *GetSTLayer();
        
        TensorData *GetLastHiddenStateOutY(int devID);
        TensorData *GetLastHiddenStateOutD(int devID);
        TensorData *GetFirstHiddenStateInD(int devID);
        
        void SetSOSData(int sosIndex);
        
    private:
        void SetChildLayerMomeryPointInitStatus();
        void CreateNetStruct();
        
        void RealeaseSubLayesInstance();

        void FirstLayerCreate(MYFC *&iFCW, MYFC *&iFCU, FusionLayer *&iFusionLayer, BiasLayer *&iBias);

        void CreateHiddenLayers(MYFC *&iFCLayer, int middleHiddenNums);

        void FirstLayerOfThisCeilForward(int devID, MYFC *iWFCLayer, MYFC *iUFCLayer, FusionLayer *iFusionLayer, BiasLayer *iBiasLayer, int seqNum);
        void FirstLayerOfThisCeilBackward(int devID, MYFC *iWFCLayer, MYFC *iUFCLayer, FusionLayer *iFusionLayer, BiasLayer *iBiasLayer, int seqNum);

        void HiddenLayerOfThisCeilBackward(int devID, MYFC *iFCLayerArray, int seqNum);
        void HiddenLayerOfThisCeilForward(int devID, MYFC *iFCLayerArray, int seqNum);
        
        void SubLayerGroupSetInLayers();
        void HiddenLayersSetInLayers(MYFC *iHiddenFC);
        void CreateSOS();
        void CreateST();
        void SubLayerGroup();
                
        //First part
        MYFC *mRWFFCLayer;        
        MYFC *mRUFFCLayer;
        FusionLayer *mFusionLayer;
        BiasLayer *mRBFBiasLayer;
        
        //Hide Part            
        MYFC *mRHFCLayer;
        int mHiddenNum;                 
        
        FormatToLayer *mSTLayer, *mXXLayer, *mSTNextLayer;
        
        FBAGroupLayer *mResultFBALayer;
        TensorData *mSOSTensor;  
        TensorData *mSTInitTensor;

        int mMaxSeqlen;                   // Max In Seqlen
        int mInVecDim;                    // input vector dim
        int mHidVecDim;                   // hidden layer dim equal out dim
        
        int mThisBatchSeqlen;
        int mIfHaveInputForXX, mIfOutResult;
        
        int inChannels, inHeight, inWidth;
        int outChannels, outHeight, outWidth;
};
#endif
