let JV = require('../jpc_value_define');
let JE = require('../jpc_rte');
let JpcCommonHelper = require('./jpc_helper_common');

let JpcCrossTabHelper = {
    getColIDX: function(cl, val) {
        let rst = -1;
        for (let i = 0; i < cl.length; i++) {
            let ca = cl[i];
            for (let j = 0; j < ca.length; j++) {
                if (ca[j] == val) {
                    rst = i;
                    break;
                }
            }
            if (rst != -1) {
                break;
            }
        }
        return rst;
    },
    pushToSeg: function(segArr, dataSeq, segIdx, sIdx, eIdx) {
        let arrIdx = [];
        for (let k = sIdx; k < eIdx; k++) {
            arrIdx.push(dataSeq[segIdx][k]);
        }
        segArr.push(arrIdx);
    },
    sortFieldValue: function(sIDX, eIDX, sortOrder, dataField, dataValSeq) {
        let tmpSeq = [];
        if ((sortOrder) && (sortOrder !== JV.TAB_FIELD_PROP_SORT_VAL_NOSORT)) {
            if (sIDX >= 0 && eIDX >= sIDX && dataValSeq.length > eIDX) {
                let reversed = 1;
                if (sortOrder === JV.TAB_FIELD_PROP_SORT_VAL_DESC) {
                    reversed = -1;
                }
                for (let i = sIDX; i <= eIDX; i++) {
                    tmpSeq.push(dataValSeq[i]);
                }
                tmpSeq.sort(function(idx1, idx2) {
                    let rst = 0;
                    // if (isNaN(parseFloat(dataField[idx1])) || isNaN(parseFloat(dataField[idx1]))) {
                    if (typeof (dataField[idx1]) === 'string' || typeof (dataField[idx1]) === 'string' ) {
                        if (dataField[idx1] > dataField[idx2]) {
                            rst = reversed;
                        } else if (dataField[idx1] < dataField[idx2]) {
                            rst = -reversed;
                        }
                    } else {
                        if ((1.0 * dataField[idx1]) > (1.0 * dataField[idx2])) {
                            rst = reversed;
                        } else if ((1.0 * dataField[idx1]) < (1.0 * dataField[idx2])) {
                            rst = -reversed;
                        }
                    }
                    return rst;
                });
            }
        }
        if (tmpSeq.length > 0) {
            for (let i = sIDX; i <= eIDX; i++) {
                dataValSeq[i] = tmpSeq[i - sIDX];
            }
        }
        return tmpSeq;
    },
    checkIfEqual: function(dataFields, seq1, seq2) {
        let rst = true;
        for (let i = 0; i < dataFields.length; i++) {
            if ((dataFields[i][seq1] !== dataFields[i][seq2])) {
                rst = false;
                break;
            }
        }
        return rst;
    },
    sortTabFields: function(tabFields, fieldSeqs, data_details, dataSeq, $CURRENT_RPT) {
        let me = this;
        let sIDX = 0, eIDX = -1, isFirstSort = true;
        for (let i = 0; i < tabFields.length; i++) {
            let tabField = tabFields[i];
            if (tabField[JV.TAB_FIELD_PROP_SORT] !== JV.TAB_FIELD_PROP_SORT_VAL_NOSORT) {
                if (isFirstSort) {
                    isFirstSort = false;
                    //first field, should sort all data items
                    for (let j = 0; j < dataSeq.length; j++) {
                        sIDX = 0;
                        eIDX = dataSeq[j].length - 1;
                        //sort the field value here
                        if (typeof(fieldSeqs[i]) === "object") {
                            let exFirstField = JE.F(fieldSeqs[i][JV.PROP_ID], $CURRENT_RPT);
                            if (exFirstField) {
                                me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT], exFirstField[JV.PROP_AD_HOC_DATA], dataSeq[j]);
                            } else {
                                //不排序（健壮性）
                            }
                        } else {
                            me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                        }
                        // me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                    }
                } else {
                    //then sort the rest fields one by one
                    for (let j = 0; j < dataSeq.length; j++) {
                        let chkFields = [];
                        for (let k = 0; k < i; k++) {
                            if (typeof(fieldSeqs[k]) === "object") {
                                let exField = JE.F(fieldSeqs[k][JV.PROP_ID], $CURRENT_RPT);
                                if (exField) {
                                    chkFields.push(exField[JV.PROP_AD_HOC_DATA]);
                                } else {
                                    chkFields.push(null);
                                }
                            } else {
                                chkFields.push(data_details[fieldSeqs[k]]);
                            }
                            // chkFields.push(data_details[fieldSeqs[k]]);
                        }
                        sIDX = 0, eIDX = -1;
                        for (let m = 1; m < dataSeq[j].length; m++) {
                            if (!(me.checkIfEqual(chkFields, dataSeq[j][m - 1], dataSeq[j][m]))) {
                                eIDX = m - 1;
                            } else if (m == dataSeq[j].length - 1) {
                                eIDX = m;
                            };
                            if (eIDX >= sIDX) {
                                if (eIDX != sIDX) {
                                    if (typeof(fieldSeqs[i]) === "object") {
                                        let exOtherField = JE.F(fieldSeqs[i][JV.PROP_ID], $CURRENT_RPT);
                                        if (exOtherField) {
                                            me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT], exOtherField[JV.PROP_AD_HOC_DATA], dataSeq[j]);
                                        } else {
                                            //不排序（健壮性）
                                        }
                                    } else {
                                        me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                                    }
                                    // me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                                }
                                sIDX = m;
                                eIDX = m - 1; //for protection purpose
                            }
                        }
                    }
                }
            }
        }
    },
    getMaxRowsPerPage: function(bands, rptTpl) {
        let rst = 1;
        let band = bands[rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW][JV.PROP_BAND_NAME]];
        if (band) {
            rst =  getMaxTabCntPerPage(rptTpl, JV.NODE_CROSS_ROW, JV.PROP_CMN_HEIGHT, band.Bottom - band.Top);
        }
        return rst;
    },
    getMaxColsPerPage: function(bands, rptTpl) {
        let rst = 1;
        let band = bands[rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL][JV.PROP_BAND_NAME]];
        if (band) {
            rst =  getMaxTabCntPerPage(rptTpl, JV.NODE_CROSS_COL, JV.PROP_CMN_WIDTH, band.Right - band.Left);
        }
        return rst;
    },
    getActualRowsHeight: function(bands, rptTpl, segments, page) {
        let rst = 1;
        let band = bands[rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW][JV.PROP_BAND_NAME]];
        if (band) {
            rst =  getActualContentAreaMeasurement(rptTpl, JV.NODE_CROSS_ROW, JV.PROP_CMN_HEIGHT, band.Bottom - band.Top, segments, page);
        }
        return rst;
    },
    getActualColsWidth: function(bands, rptTpl, segments, page) {
        let rst = 1;
        let band = bands[rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL][JV.PROP_BAND_NAME]];
        if (band) {
            rst =  getActualContentAreaMeasurement(rptTpl, JV.NODE_CROSS_COL, JV.PROP_CMN_WIDTH, band.Right - band.Left, segments, page);
        }
        return rst;
    },
    chkTabEnd: function(tabType, rptTpl, bands, sortedSequence, segIdx, preRec, nextRec) {
        let me = this, rst = true;
        let remainAmt = preRec + nextRec - sortedSequence[segIdx].length;
        rst = me.hasEnoughSpace(tabType, rptTpl, bands, remainAmt);
        return rst;
    },
    hasEnoughSpace: function (tabType, rptTpl, bands, remainAmt) {
        if (remainAmt < 0) return false;
        let rst = true, measurement = 1.0, douDiffForCompare = 0.00001;
        let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
        let band = null;
        if (rptTpl[JV.NODE_CROSS_INFO][tabType]) {
            band = bands[rptTpl[JV.NODE_CROSS_INFO][tabType][JV.PROP_BAND_NAME]];
        }
        if (band != null && band != undefined) {
            if (tabType === JV.NODE_CROSS_ROW_SUM || tabType === JV.NODE_CROSS_ROW_EXT) {
                measurement = 1.0 * rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW][JV.PROP_CMN_HEIGHT] * unitFactor;
                let spareHeight = measurement * remainAmt;
                let douH = 1.0 * (band.Bottom - band.Top);
                rst = (spareHeight >= douH) || (spareHeight - douH <= douDiffForCompare);
            } else if (tabType === JV.NODE_CROSS_COL_SUM) {
                measurement = 1.0 * rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL][JV.PROP_CMN_WIDTH] * unitFactor;
                let spareWidth = measurement * remainAmt;
                let douW = 1.0 * (band.Right - band.Left);
                rst = (spareWidth >= douW) || (spareWidth - douW <= douDiffForCompare);
            }
        }
        return rst;
    },
    initialPageStatus: function (pageStatus) {
        pageStatus[JV.STATUS_NORMAL] = true;
        pageStatus[JV.STATUS_REPORT_START] = false;
        pageStatus[JV.STATUS_REPORT_END] = false;
        pageStatus[JV.STATUS_SEGMENT_START] = false;
        pageStatus[JV.STATUS_SEGMENT_END] = false;
        pageStatus[JV.STATUS_GROUP] = false;
        pageStatus[JV.STATUS_CROSS_ROW_END] = false;
        pageStatus[JV.STATUS_CROSS_COL_END] = false;
    }
};

function getMaxTabCntPerPage(rptTpl, tabNodeName, tabMeasurePropName, measureForCal) {
    let rst = 1;
    if (rptTpl[JV.NODE_CROSS_INFO][tabNodeName]) {
        let tab = rptTpl[JV.NODE_CROSS_INFO][tabNodeName];
        let maxFieldMeasure = 1.0;
        if (JV.CAL_TYPE_ABSTRACT === JpcCommonHelper.getPosCalculationType(tab[JV.PROP_CALCULATION])) {
            let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
            maxFieldMeasure = 1.0 * rptTpl[JV.NODE_CROSS_INFO][tabNodeName][tabMeasurePropName] * unitFactor;
        } else {
            maxFieldMeasure = measureForCal * rptTpl[JV.NODE_CROSS_INFO][tabNodeName][tabMeasurePropName] / JV.HUNDRED_PERCENT;
        }
        rst = Math.floor(measureForCal / maxFieldMeasure);
    }
    return rst;
};

function getActualContentAreaMeasurement(rptTpl, tabNodeName, tabMeasurePropName, measureForCal, segments, page) {
    let rst = 1;
    if (rptTpl[JV.NODE_CROSS_INFO][tabNodeName]) {
        let tab = rptTpl[JV.NODE_CROSS_INFO][tabNodeName];
        let maxFieldMeasure = 1.0;
        if (JV.CAL_TYPE_ABSTRACT === JpcCommonHelper.getPosCalculationType(tab[JV.PROP_CALCULATION])) {
            let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
            maxFieldMeasure = 1.0 * rptTpl[JV.NODE_CROSS_INFO][tabNodeName][tabMeasurePropName] * unitFactor;
        } else {
            maxFieldMeasure = measureForCal * rptTpl[JV.NODE_CROSS_INFO][tabNodeName][tabMeasurePropName] / JV.HUNDRED_PERCENT;
        }
        if (segments.length >= page) {
            rst = segments[page - 1].length * maxFieldMeasure;
        }
    }
    return rst;
};

module.exports = JpcCrossTabHelper;