#ifndef LCF_NET_H_
#define LCF_NET_H_
#include "tensorOperate.h"
#include "globalMemPoolFloat.h"
#include "commStruct.h"
#include "tinyxml2.h"
#include "devicesBatchDispatch.h"

/**************************************/
// cPool for computer mempry
// mPool main for para(conv and FC etc.)
// bPool back for para(conv and FC etc.)
struct CcnnContext {
    int devicesNum;
    unsigned char *deviceId;
    GlobalMemPoolFloat *cPool;
    GlobalMemPoolFloat *mPool;
    GlobalMemPoolFloat *bPool;
    TensorOperate **pTensorOperate;
    int layNum;
    int maxIterNum;
    int saveIterNum;
    float minStopError;  
    char weightFile[128];
    int netType;
    int method;
    int mBatchNum;
    int ifLoadWeight;
    DevicesBatchDisptach *mDevicesBatchDisptach;
};

class TensorOperate;
class LcfNet {
    public:        

        //Create Net
        static struct CcnnContext *CreateNetFromXML(const char *cnfXMLName, const int method, int ifLoadWeight);
        static void LoadNetMemAndPara(struct CcnnContext *pCtx);
        
        //Train 
        static void NetTrainClassify(struct CcnnContext *pCtx, PicInfo *trainImgs, int *type, int sampleNum);
        static void NetTrainSeg(struct CcnnContext *pCtx, PixClassify *pSeg, int segClsNum, PicInfo *trainImgs, PicInfo *labelData, int sampleNum);
        static void NetTrainObjectsDet(struct CcnnContext *pCtx, PicInfo *trainImgs, struct PicGroundTrueBox *trainPGBox, int sampleNum);
        static void NetTrainMultiRegress(struct CcnnContext *pCtx, float *trainData, float *lableNum, int sampleNum, int inputDim, int outputDim);
        static void NetTrainVectorCls(struct CcnnContext *pCtx, float *trainData, float *lableType, int sampleNum, int inputDim);
        static void MainTrainRNNRegress(struct CcnnContext *pCtx, float *trainData, float *lableNum, int seqNum, int batchCount, int inputDim, int outputDim);
        static void MainTrainNLP(struct CcnnContext *pCtx, int *trainInfo, int *lableInfo, int sentenceCount, \
                                 int *oneSentenceSeqNum, int *oneLabelSeqNum, int inputDim, int outputDim);

        //inference
        static void NetPredictSeg(struct CcnnContext *pCtx, float *inImg, unsigned char **hotMap, float **hotMapPab, int *h, int *w);
        static void NetPredictClassify(struct CcnnContext *pCtx, float *inImg, int *outType, float *typePab);
        static struct PredictBox *NetPredictOneStageDet(struct CcnnContext *pCtx, float *inImg, int *outNum, float pab);
        static float *NetPredictMultiRegress(struct CcnnContext *pCtx, float *pData);
        static void NetPredictVecClassify(struct CcnnContext *pCtx, float *pData, int *&outType, float *&typePab);

        //realease net
        static void RealeaseCcnnStructMemory(struct CcnnContext *pCtx);

        static int ReadInputHeightWidth(struct CcnnContext *pCtx);
        static int ReadInputChannels(struct CcnnContext *pCtx);
        static int ReadOutputChannels(struct CcnnContext *pCtx);
        static int ReadInputMaxSeqNum(struct CcnnContext *pCtx);
        
        static TensorOperate *GetClassEntityById(struct CcnnContext *pCtx, int hisId);
        static TensorOperate *GetClassEntityByIndex(struct CcnnContext *pCtx, int index);
        static TensorOperate **GetInLayersStruct(struct CcnnContext *pCtx, int *inID, int len);
        static TensorOperate **GetOutLayersStruct(struct CcnnContext *pCtx, TensorOperate *iLcfTensorOperate, int *outLen);
        static void AllocGlobalMem(int devID, GlobalMemPoolFloat *aPool, GlobalMemPoolFloat *mPool, GlobalMemPoolFloat *bPool, \
                                   float apiMem, int apiType, float pMainMem, int mainType, float pBackMem, int backType);
        static void AllocGlobalMemFromXML(const char *cnfXMLName, int devID, GlobalMemPoolFloat *aPool, GlobalMemPoolFloat *mPool, GlobalMemPoolFloat *bPool);
        static void GetDWStopFreezeBehavoir(tinyxml2::XMLElement *userNode, int *outD, int *outW);
        static int GetIntNode(tinyxml2::XMLElement *userNode, const char *nodeStr, int defaultInt);
        static int GetIntNode(tinyxml2::XMLElement *userNode, const char *nodeStr);
        static float GetFloatNode(tinyxml2::XMLElement *userNode, const char *nodeStr, float defaultFloat);
        static float GetFloatNode(tinyxml2::XMLElement *userNode, const char *nodeStr);
        static void SetInLayersArrayFromXMLNodeCnf(tinyxml2::XMLElement *userNode, TensorOperate *iLcfTensorOperate);
        static void SetALLLayersIfLoadPreWeightAndAndMethod(struct CcnnContext *pCtx);
        static void CreateNetLayersFromXML(const char *cnfXMLName, struct CcnnContext *pCtx);
        static void CreateNetParaMemAndInOutLayersBuild(struct CcnnContext *pCtx);
        static void SetALLLayersInDataLayerPoint(struct CcnnContext *pCtx);
        static void SetALLLayersOutDataLayerPoint(struct CcnnContext *pCtx);
        static void SetALLLayersCreateSaveInYOutDPoint(struct CcnnContext *pCtx);
        static void LayersCreateParaAndInstance(struct CcnnContext *pCtx);
        static void ShowErrorForIteration(int itIndex, float errNum);     
        static float BatchTrain(struct CcnnContext *pCtx, float *picsMemory, void *labelMem, int srcH);
        static void SaveTrainWeight(struct CcnnContext *pCtx, int iterNum);
        static void LoadWeight(struct CcnnContext *pCtx);
        static int GetSegHotMapHW(struct CcnnContext *pCtx);
        static void OneSampleForWard(struct CcnnContext *pCtx, float *inImg);
        static int GetMultiRegressIfNormInFromNet(struct CcnnContext *pCtx);
        static int GetMultiRegressIfNormOutFromNet(struct CcnnContext *pCtx);
        static void ReadObjectsDetSamples(int *picNum, struct PicGroundTrueBox *&gtBox, PicInfo *&trainImgs, int mPicHWLen, char *strNameList);
        static void ReadSemanticSamples(int *picNum, PicInfo *&trainImgs, PicInfo *&labelData, int mPicHWLen);
        static void ReadImgClassifySamples(int *picNum, PicInfo *&trainImgs, int *&tmpLabel, int mPicHWLen);
        static void ReadMultiRegressSamples(int *sampleNum, float *&trainData, float *&lableNum, int inputDim, int outputDim, int ifNormIn, int ifNormOut);
        static void ReadVectorClassifySamples(int *sampleNum, float *&trainData, int *&lableType, int inputDim);
        static char *ReadSampleClassNameStrList(const char *mCnfXMLName);
        static struct RNNDataInfo *ReadRNNInputData(int inDim, int seqNum, int mBatchNum, int ifNormIn, int ifNormOut);
        static void RealeaseRNNDDataStruct(struct RNNDataInfo *p);

        static void ALLLayersLoadWeight(struct CcnnContext *pCtx);
        static void SetBatchSeqConfigForThisBatch(int devID, struct CcnnContext *pCtx, struct BatchSeqStruct *pBatchSeqStruct);
        
        static int GetThisBatchSampleSize(struct BatchSeqStruct *pBatchSeqStruct);
        static int GetThisBatchLabelSize(struct BatchSeqStruct *pBatchSeqStruct);
        static void RandomSampleLabelBatchSeq(int *&tData, int *&lData, int *&newTSeq, int *&newLSeq, int batNum, int *trainInfo, \
                                              int *lableInfo, int sentenceCount, int *oneSentenceSeqNum, int *oneLabelSeqNum, int k);
                                              
        static struct BatchSeqStruct *CreateSampleLabelVector(float *&trainData, float *&lableNum, int k, int *trainDataValue, \
                                                              int *lableNumValue, int *oneSentenceSeqNum, int *oneLabelSeqNum, \
                                                              int mBatchNum, int inputDim, int outputDim);
                                                              
        static void ShowDebugMemoryPoolInfo(struct CcnnContext *pCcnnContext);
};
#endif
