/* eslint-disable */

/* 后处理图片 by zhangmiao06 */
// let preTestRun = index => {
//     let img = document.getElementById('image');
//     img.src = tempPic[index];
//     img.onload = function () {
//         testRun(testOutput.data[index], img);
//     };
// };

import models from '../utils/models';

const isSimilar = (r1, r2, threshold = 5) => {
    return Math.max(Math.abs(r1[0] - r2[0]), Math.abs(r1[1] - r2[1])) < threshold;
    // return Math.abs((r1[0] + r1[1] + r1[2] + r1[3]) - (r2[0] + r2[1] + r2[2] + r2[3])) < threshold;
}

// sigmoid
let sigmoid = (x) => {
    if (x < -100) {
        return 0.0;
    }

    return 1 / (1 + Math.exp(-x));
};

// transpose
let transpose = (data) => {
    let shape = data.shape;
    let transposeShape = data.transposeShape;
    let formatData = data.data;
    let formatData2 = [];
    for (let n = 0; n < shape[transposeShape[0]]; n++) {
        let nData = [];
        for (let c = 0; c < shape[transposeShape[1]]; c++) {
            let cData = [];
            for (let row = 0; row < shape[transposeShape[2]]; row++) {
                let rowData = [];
                for (let col = 0; col < shape[transposeShape[3]]; col++) {
                    let tempArr = [n, c, row, col];
                    let newN = n;
                    let newC = c;
                    let newW = row;
                    let newH = col;
                    transposeShape.forEach((item, index) => {
                        switch (item) {
                            case 0:
                                newN = tempArr[index];
                                break;
                            case 1:
                                newC = tempArr[index];
                                break;
                            case 2:
                                newW = tempArr[index];
                                break;
                            case 3:
                                newH = tempArr[index];
                        }
                    });
                    rowData.push(formatData[newN][newC][newW][newH]);
                }
                cData.push(rowData);
            }
            nData.push(cData);
        }
        formatData2.push(nData);
    }
    return formatData2;
};

// reshape
const reshape = (data) => {
    let formatData2 = data.data;
    let shape = data.shape;
    let reshapeShape = data.reshapeShape;
    // 1.变成一维
    let tempData = reshapeOne({
        data: formatData2,
        shape: shape
    });
    // 2.变成多维
    let formatData3 = reshapeMany({
        data: tempData,
        reshapeShape: reshapeShape
    });
    return formatData3;
};

// 变成一维
const reshapeOne = (data) => {
    let formatData2 = data.data;
    let shape = data.shape;
    let tempData = [];
    for (let n = 0; n < shape[0]; n++) {
        for (let c = 0; c < shape[1]; c++) {
            for (let row = 0; row < shape[2]; row++) {
                for (let col = 0; col < shape[3]; col++) {
                    tempData.push(formatData2[n][c][row][col]);
                }
            }
        }
    }
    return tempData;
};

// 变成多维
const reshapeMany = data => {
    let tempData = data.data;
    let reshapeShape = data.reshapeShape;
    let formatData3 = [];
    for (let n = 0; n < reshapeShape[0]; n++) {
        let nData = [];
        for (let c = 0; c < reshapeShape[1]; c++) {
            let cData = [];
            for (let row = 0; row < reshapeShape[2]; row++) {
                let rowData = [];
                for (let col = 0; col < reshapeShape[3]; col++) {
                    let tempN = n * reshapeShape[1] * reshapeShape[2] * reshapeShape[3];
                    let tempC = c * reshapeShape[2] * reshapeShape[3];
                    let tempRow = row * reshapeShape[3];
                    rowData.push(tempData[tempN + tempC + tempRow + col]);
                }
                cData.push(rowData);
            }
            nData.push(cData);
        }
        formatData3.push(nData);
    }
    return formatData3;
};

export default class PostProcess {
    constructor(options) {
        this.modelConfig = models[options.modelName];
        this.count = 0;
        this.lastRect = [0, 0, 0, 0]
    }
    
    run(data, img, callback) {
        let {from, to} = this.modelConfig.outputShapes;
        let shape = [].concat(from).reverse();
        // 1.从一维数组到1*25*19*19
        let formatData = reshapeMany({
            data: data,
            reshapeShape: shape
        });
        // console.log('一维到多维', formatData);
        // 2.从1*25*19*19 到 19*19*25*1
        let formatData2 = transpose({
            data: formatData,
            shape: shape,
            transposeShape: [2, 3, 1, 0]
        });
        // console.log('transpose', formatData2);
        // 3.从19*19*25*1到19*19*5*5
        let formatData3 = reshape({
            data: formatData2,
            // shape: [19, 19, 25, 1],
            // reshapeShape: [19, 19, 5, 5]
            shape: from,
            reshapeShape: to
        });
        // console.log('reshape', formatData3);
        // 4.运算
        let finalData = this.handleFinal(formatData3, shape, img);
        // console.log('final', finalData);
        // 5.处理画布
        // finalData.length && handleCanvas(finalData, img);
        this.handleDiv(finalData, img, callback);
    }

    calSize(img) {
        let w1 = img.width;
        let h1 = img.height;
        let wh1 = Math.max(w1, h1);
        let factor = this.modelConfig.feedShape.fw / wh1;
        // let factor = 608.0 / wh1;
        let width = Math.round(w1 * factor);
        let height = Math.round(h1 * factor);
        return [w1, h1, width, height];
    }

    // 处理运算
    handleFinal(formatData3, shape, img) {
        let finalData = [];
        let c = shape[2];
        let [w1, h1, width, height] = this.calSize(img);
        let factorX = Math.max(width, height) / width;
        let factorY = Math.max(width, height) / height;

        let maxProb = 0.0;
        let anchors = [[1.603231, 2.094468], [6.041143, 7.080126], [2.882459, 3.518061], [4.266906, 5.178857], [9.041765, 10.66308]];

        for (let i = 0; i < shape[2]; i++) {
            for (let j = 0; j < shape[3]; j++) {
                for (let k = 0; k < anchors.length; k++) {
                    let [a1, a2, a3, a4, prob] = formatData3[i][j][k];
                    prob = sigmoid(prob);
                    if (prob > maxProb && prob >= 0.5) {
                        let ctx = (j + sigmoid(a1)) / c * factorX;
                        let cty = (i + sigmoid(a2)) / c * factorY;
                        let col = Math.exp(a3) * anchors[k][0] / c * factorX;
                        let row = Math.exp(a4) * anchors[k][1] / c * factorY;
                        let x = (ctx - (col / 2));
                        let y = (cty - (row / 2));
                        finalData.push([x * w1, y * h1, col * w1, row * h1, prob]);
                    }

                }
            }
        }
        return finalData;
    }

    handleDiv(finalData, img, callback) {
        if (finalData.length < 1) {
            callback();
            return false;
        }
        let maxIndex = 0;
        if (finalData.length > 1) {
            for (let i = 1; i < finalData.length; i++) {
                if (finalData[i].prob > finalData[maxIndex].prob) {
                    maxIndex = i;
                }

            }
        }

        let [demoLeft, demoTop, demoWidth, demoHeight] = finalData[maxIndex];
        if (!isSimilar(this.lastRect, [demoLeft, demoTop, demoWidth, demoHeight])) {
            callback([demoWidth, demoHeight,demoLeft, demoTop]);
        };
        this.lastRect = [demoLeft, demoTop, demoWidth, demoHeight];
    }

    // 处理画布
    handleCanvas(finalData, img) {
        let myCanvas = document.getElementById('myCanvas');
        let [w1, h1, width, height] = calSize(img);
        myCanvas.width = w1;
        myCanvas.height = h1;
        let ctx = myCanvas.getContext('2d');
        // ctx.drawImage(img, 0, 0, w1, h1);

        // finalData.forEach((demoArr, index) => {
        // let [demoLeft, demoTop, demoWidth, demoHeight, prob] = demoArr;
        let [demoLeft, demoTop, demoWidth, demoHeight, prob] = finalData[0];
        ctx.beginPath();
        ctx.lineWidth = 4;
        ctx.strokeStyle = 'red';
        ctx.moveTo(demoLeft, demoTop);
        ctx.lineTo(demoLeft + demoWidth, demoTop);
        ctx.lineTo(demoLeft + demoWidth, demoTop + demoHeight);
        ctx.lineTo(demoLeft, demoTop + demoHeight);
        ctx.closePath();
        ctx.stroke();
        // });
    }
}

