#ifndef ONE_STAGE_DET_H_
#define ONE_STAGE_DET_H_

#include "tensorOperate.h"
#include "commStruct.h"

#define SECOND_RULE_IOU 0.5F
#define FLAG_INIT 0
#define FLAG_WAITCFM_P 1
#define FLAG_CONFIRM_P 2
#define FLAG_WAITCFM_N 3
#define FLAG_CONFIRM_N 4
#define PBOX_NMS_INIT 0
#define PBOX_NMS_SAVE 1
#define PBOX_NMS_DELETE 2
#define PBOX_NMS_GATE 0.25F
#define PN_COFF 3
#define PERIOR_KEEP_NUM 3000
#define TRAIN_LOST_GATE_VALIE 0.3F

class OneStageDetLayer : public TensorOperate
{
    public:
        OneStageDetLayer(int ifType, int iID, int iMaxSeqNum, LayerType iLayType, DevicesBatchDisptach *iDevicesBatchDisptach, \
                         SLTYPE lossType, int netClassNum, int iKeepTopMatchNum);
        virtual ~OneStageDetLayer();
        void SetLostType(SLTYPE lossType);
        void SetInParaComputerOtherParaAndAllMem();
        void InputTrainLabelData(struct PicGroundTrueBox *mPicBoxList);

        virtual void CreateDefaultBox() {};
        virtual int PositiveSampleSelect(int devID, int n, int idx) {return 1;};
        virtual void NegativeSampleSelect(int devID, int n, int pNum, int idx) {};
            
        void CompuateOutY(int devID, int idx);
        void CompuateOutD(int devID, int idx);
        void UpdateThisLayerWeight();
        void SaveLayerWeight(int n);
        void LoadLayerWeight();
        void ComputerYMemRealease(int devID);
        void ComputerDMemRealease(int devID);
        void ResetDefaultBoxForBeginNewOnePic(int devID);

        struct PredictBox *NMSOutputBox(int devID, int batchIndex, int *outNum, float pab, int idx);

        void ComputeAndCreateOutYInDTensorInfo();
        void CreateParaAndInstance();
        float GetThisBatchAveLost();
        
        void SetChildLayerMomeryPointInitStatus();
        void RealeaseChildLayerMemory();

        int GetMaxIOUToGroundTrueBox(int devID, int batchIndex, struct Box *dBox, float *outIOU);
        void GetOnePicSemiPositiveBoxFirstRule_CPU(int devID, int batchIndex);
        void GetOnePicSemiPositiveBoxSecondRule_CPU(int devID, int batchIndex);
#ifdef _CMEM_USE_GPU_
        void GetOnePicSemiPositiveBoxFirstRule_GPU(int devID, int batchIndex);
        void GetOnePicSemiPositiveBoxSecondRule_GPU(int devID, int batchIndex);
        void ConfirmNegativeSample_GPU(int devID, int batchIndex, int confirmP, int idx);
#endif
        int GetDefaultBoxIndexByPriorBoxOffset(int pOffset);
        int ConfirmPostiveSample(int devID, int batchIndex, int idx);
        void ConfirmNegativeSample_CPU(int devID, int batchIndex, int confirmP, int idx);

        void ComputerOnePicD(int devID, int batchIndex, int idx);

        void GetMaxConfAndIndexOfPBox(struct PredictBox *pBox, int bNum, int *mIndex, float *mValue);
        void NMSBoxList(struct PredictBox *pBox, int bNum, int mIndex);
        float GPDBoxLocLost(struct Box gBox, struct Box pBox, struct Box dBox, float *sbx, float *sby, float *sbw, float *sbh);
        float ComputerOnePicLocAndConfLost(int devID, int batchIndex, int idx);
        
        struct DefaultBox *GetDefaultBox(int devID, int oneIndex);
        struct PicGroundTrueBox *GetPicGroundTrueBox(int devID, int batchIndex);
        
        MemoryHandle *GetDefaultBoxHandle(int devID);

        void SavePredictBox(int batchIndex, float pab);
        TensorData *mDefaultBoxHandle;              // Handle for defaultBox
        struct PicGroundTrueBox *mPicGroundTrueBox; // mPicGroundTrueBox[batchNum]
        int *PSNum;                                 // PSNum[batchNum] is positive sample box number
        int *NSNum;                                 // NSNum[batchNum] is negative sample box number
        int classNum;                               // num of classify.
        int keepTopMatchNum;                        // Get top this num prior box from sort location and confidence lost list.
        int mAllDefaultBoxNum;                      // number of defaultBox for all devices
        float *mBatchSumLost;                       // one batchNum toall conf and location lost
        float mVaiance[4];                          // variance of box
        SLTYPE mLostType;                           // SL or FL
};

#endif
