#include "UtsusemiFilterBase.hh"
//////////////////////////////////////////////////////////
UtsusemiFilterBase::
UtsusemiFilterBase(){
    InitializeBase();
}
//////////////////////////////////////////////////////////
UtsusemiFilterBase::
~UtsusemiFilterBase(){
}
//////////////////////////////////////////////////////////
void UtsusemiFilterBase::
InitializeBase(){
    isFilterReady = false;
    filterCaseTable = NULL;
    filterPulseIdList.clear();
    numOfCases = 1;
    _CaseAmbiguity = 0;
    _CaseAmbiguity_params.clear();
}
//////////////////////////////////////////////////////////
UInt4 UtsusemiFilterBase::
PutNumOfCases(){
    return numOfCases;
}
//////////////////////////////////////////////////////////
std::vector<UInt4> UtsusemiFilterBase::
PutListOfCases(){
    std::vector<UInt4> ret;
    return ret;
}
//////////////////////////////////////////////////////////
void UtsusemiFilterBase::
DumpCaseTable(){
    if (filterCaseTable==NULL){
        UtsusemiError( "UtsusemiFileterBase::DumpCaseTable > No CaseTable." );
        return;
    }
    for (UInt4 frm=0;frm<filterCaseTable->size();frm++){
        if (filterCaseTable->at(frm)!=NULL){
            std::cout << "frameNo = "<<frm<<" case = ";
            for (UInt4 j=0;j<(filterCaseTable->at(frm)->size()-1);j++){
                std::cout << filterCaseTable->at(frm)->at(j) << ",";
            }
            std::cout << filterCaseTable->at(frm)->back() << std::endl;
        }
    }

}
//////////////////////////////////////////////////////////
void UtsusemiFilterBase::
Clear(){
    if (filterCaseTable!=NULL){
        for (UInt4 i=0;i<filterCaseTable->size();i++)
            if (filterCaseTable->at(i)!=NULL)
                delete filterCaseTable->at(i);
        delete filterCaseTable;
        filterCaseTable=NULL;
    }
    filterPulseIdList.clear();
}
//////////////////////////////////////////////////////////
Int4 UtsusemiFilterBase::
ReadCaseInfoFile( std::string caseInfoFile ){
    return 0;
}
//////////////////////////////////////////////////////////
Int4 UtsusemiFilterBase::
ReadCaseEventFiles( UInt4 index, std::vector<std::string> evt_files, std::vector< std::vector<UInt8> > t0b_index_list ){
    return 0;
}
//////////////////////////////////////////////////////////
Int4 UtsusemiFilterBase::
ReadCaseEvent( UInt4 index, std::vector<std::string> evt_files, std::vector<std::string> t0b_files ){
    return -1;
}
//////////////////////////////////////////////////////////
void UtsusemiFilterBase::
MakeFilterTables(){
}
//////////////////////////////////////////////////////////
UInt4 UtsusemiFilterBase::
GetCaseFromTof( const UInt4 pixelId, Double* tof, std::vector<UInt4>* caseVec ){
    return 0;
}
//////////////////////////////////////////////////////////
void UtsusemiFilterBase::
CheckAmbiguousFrame(){
    if (filterCaseTable==NULL){
        UtsusemiError( "UtsusemiFilterBase::CheckAmbigousFrame >> No CaseTable." );
        return;
    }
    if (_CaseAmbiguity==1){ // Accept the case that only one case exists in a frame, ignore the frame if many cases are in the frame
        for (UInt4 frm=0;frm<filterCaseTable->size();frm++){
            if (filterCaseTable->at(frm)!=NULL){
                UInt4 num_cases = (UInt4)(filterCaseTable->at(frm)->size());
                if (num_cases==2) continue;
                if ((num_cases==4)&&(filterCaseTable->at(frm)->back()==0)) continue;
                filterCaseTable->at(frm)->clear();
                filterCaseTable->at(frm)->push_back(0);
                filterCaseTable->at(frm)->push_back(0);
            }
        }

    }
    if (_CaseAmbiguity==2){ // Use the case which most large number of cases in the frame
        for (UInt4 frm=0;frm<filterCaseTable->size();frm++){
            if (filterCaseTable->at(frm)!=NULL){
                UInt4 num_cases = (UInt4)(filterCaseTable->at(frm)->size());
                if (num_cases==2) continue;
                if ((num_cases==4)&&(filterCaseTable->at(frm)->back()==0)) continue;
                std::vector<UInt4> case_list;
                for (UInt4 i=0;i<filterCaseTable->at(frm)->size();i+=2){
                    UInt4 a_case=filterCaseTable->at(frm)->at(i);
                    if ((a_case+1)>case_list.size()) case_list.resize( (a_case+1),0 );
                    case_list[a_case]++;
                }
                UInt4 max_val=0;
                UInt4 max_case = 0;
                for (UInt4 i=0;i<case_list.size();i++){
                    if (case_list[i]>max_val){
                        max_val=case_list[i];
                        max_case=i;
                    }
                }
                filterCaseTable->at(frm)->clear();
                filterCaseTable->at(frm)->push_back(max_case);
                filterCaseTable->at(frm)->push_back(0);
            }
        }
    }
    if (_CaseAmbiguity==3){ // Use first CaseId
        std::pair<UInt4,UInt4> tof_clk_range;
        tof_clk_range.first=0;
        tof_clk_range.second=1599960; // 159960 [clocks] = 39999 [micro-sec] : if tof is over this value, the signal is in next frame
                                      // This is for using single and first frame (40msec).
                                      // If you use seconds frame or over, you must shift tof range to suitable of the frame.
                                      // |Id1,0| -> accept Id1
                                      // |Id1,0,Id2,40000| -> Id2 is first Id, accept Id2 ( Id1 is the last id of previous frame )
                                      // |Id1,0,Id2,2000000| -> Id2 is not first Id becase of tof-out-range, accept only Id1
        if (_CaseAmbiguity_params.size()>=2){
            tof_clk_range.first = (UInt4)(_CaseAmbiguity_params[0]/MLF_NEUNET_CLOCK_MICROSEC); // [micro-sec] -> [clocks]
            tof_clk_range.second= (UInt4)(_CaseAmbiguity_params[1]/MLF_NEUNET_CLOCK_MICROSEC);
        }

        UInt4 last_case=0;
        UInt4 selected_case = 0; // last_case in this frame is not selected_case.
        for (UInt4 frm=0;frm<filterCaseTable->size();frm++){
            if (filterCaseTable->at(frm)!=NULL){
                selected_case =0;
                UInt4 num_cases = (UInt4)(filterCaseTable->at(frm)->size());
                if (num_cases==2) {
                    selected_case = filterCaseTable->at(frm)->at(0);
                    last_case = selected_case;
                    continue;
                }
                if ((num_cases==4)&&(filterCaseTable->at(frm)->back()==0)) {
                    selected_case = filterCaseTable->at(frm)->at(2);
                    last_case = selected_case;
                    //continue;
                }else if (filterCaseTable->at(frm)->at(0)==last_case){
                    UInt4 tof_clk = filterCaseTable->at(frm)->at(3);
                    if ((tof_clk>=tof_clk_range.first)&&(tof_clk<=tof_clk_range.second))
                        selected_case = filterCaseTable->at(frm)->at(2);
                    else
                        selected_case = last_case;
                    last_case = filterCaseTable->at(frm)->at(num_cases-2);
                }else{
                    selected_case = filterCaseTable->at(frm)->at(0);
                    last_case = selected_case;
                }
                /*
                if (filterCaseTable->at(frm)->at(0)==last_case){
                    last_case = filterCaseTable->at(frm)->at(2);
                }else{
                    last_case = filterCaseTable->at(frm)->at(0);
                }
                */

                filterCaseTable->at(frm)->clear();
                //filterCaseTable->at(frm)->push_back(last_case);
                filterCaseTable->at(frm)->push_back(selected_case);
                filterCaseTable->at(frm)->push_back(0);
            }
        }
    }
}
