/**
 * @file 工具类
 * @author yangmingming
 */
/* eslint-disable */
export default {
    // todo: 适用2维矩阵乘法，以后实现通用版本
    getReshapeInPaddle(inputShape = [], counterShape = [], outShape = []) {
        let total = inputShape.reduce((all, num) => all * num);
        if (outShape.length === 1) {
            return [1, total];
        } else {
            return [outShape[0], total / outShape[0]];
        }
    },

    getBroadcastShapeInPaddle(shapeA= [], shapeB = [], axis = 1) {
        // todo: 简易版本，以后需要实现一个通用版本
        let bigger = shapeA;
        let result = shapeB;
        if (shapeA.length - shapeB.length < 0) {
            bigger = shapeB;
            result = shapeA;
        }
        return result.concat(bigger.slice(axis));
    },

    getBroadcastDims(inShape = [], outShape = []) {
        const inRank = inShape.length;
        const dims = [];
        for (let i = 0; i < inRank; i++) {
            const dim = inRank - 1 - i;
            const a = inShape[dim] || 1;
            const b = outShape[outShape.length - 1 - i] || 1;
            if (b > 1 && a === 1) {
                dims.unshift(dim);
            }
        }
        return dims;
    },

    getBroadcastShape(shapeA = [], shapeB = []) {
        const result = [];
        const max = Math.max(shapeA.length, shapeB.length);
        for (let i = 0; i < max; i++) {
            let a = shapeA[shapeA.length - i - 1];
            if (a === null) {
                a = 1;
            }
            let b = shapeB[shapeB.length - i - 1];
            if (b === null) {
                b = 1;
            }
            if (a === 1) {
                result.unshift(b);
            } else if (b === 1) {
                result.unshift(a);
            } else if (a !== b) {
                return null;
            } else {
                result.unshift(a);
            }
        }
        return result;
    },

    applyFilterWinograd(data, shape) {
        const [b, c, h, w] = shape;
        let offset = 0;
        let index = 0;
        const result = new Float32Array(b * c * 16);
        // h和w是3、3
        const size2D = 9;
        for (let i = 0; i < b; i++) {
            // let index = i * c * size2D;
            for (let j = 0; j < c; j++) {
                // index += j * size2D;
                const filter = data.subarray(index, index + size2D);
                const [f11, f12, f13, f21, f22, f23, f31, f32, f33] = filter;
                const square = [
                    f11,
                    0.5 * f11 + 0.5 * f12 + 0.5 * f13,
                    0.5 * f11 - 0.5 * f12 + 0.5 * f13,
                    f13,
                    0.5 * f11 + 0.5 * f21 + 0.5 * f31,
                    0.25 * f11 + 0.25 * f12 + 0.25 * f13 + 0.25 * f21 + 0.25 * f22 + 0.25 * f23 + 0.25 * f31 + 0.25 * f32 + 0.25 * f33,
                    0.25 * f11 - 0.25 * f12 + 0.25 * f13 + 0.25 * f21 - 0.25 * f22 + 0.25 * f23 + 0.25 * f31 - 0.25 * f32 + 0.25 * f33,
                    0.5 * f13 + 0.5 * f23 + 0.5 * f33,
                    0.5 * f11 - 0.5 * f21 + 0.5 * f31,
                    0.25 * f11 + 0.25 * f12 + 0.25 * f13 - 0.25 * f21 - 0.25 * f22 - 0.25 * f23 + 0.25 * f31 + 0.25 * f32 + 0.25 * f33,
                    0.25 * f11 - 0.25 * f12 + 0.25 * f13 - 0.25 * f21 + 0.25 * f22 - 0.25 * f23 + 0.25 * f31 - 0.25 * f32 + 0.25 * f33,
                    0.5 * f13 - 0.5 * f23 + 0.5 * f33,
                    f31,
                    0.5 * f31 + 0.5 * f32 + 0.5 * f33,
                    0.5 * f31 - 0.5 * f32 + 0.5 * f33,
                    f33
                ];
                result.set(square, offset);
                offset += 16;
                index += size2D;
            }
        }
        return result;
    },

    /**
     * 获取texture形状和补0个数
     * @param shape {Array} tensor的形状
     * @return {{shape: *[], zeroNumber: number}} {Object} texture信息
     */
    getTextureInfoFromTensorShape(shape = [], isPacked = false) {
        let b = shape[0];
        let c = shape[1];
        let h = shape[2];
        let w = shape[3];
        let height = b * h;
        let width = c * w;
        let offsetX = 0;
        let offsetY = 0;
        // 安卓和ios的max texture size是4096, 改造存储空间(2bh, cw / 2)
        let exceedMax = false;
        if (height > 4096 || width > 4096) {
            height *= 2;
            width = c * (Math.ceil(w / 2));
            exceedMax = true;
        }
        if (isPacked) {
            // 紧凑布局
            height = b * c * Math.ceil(h / 2);
            width = Math.ceil(w / 2);
            offsetX = w % 2;
            offsetY = h % 2;
        }
        return {
            offsetX,
            offsetY,
            exceedMax,
            shape: [4, height, width],
            zeroNumber: 0
        };
    },

    // 获取数组中的最大值和索引
    getMaxItem(datas = []) {
        let max = Math.max.apply(null, datas);
        let index = datas.indexOf(max);
        return {value: max, index};
    },

    // 压缩
    async loadShader(name) {
        let shader = await fetch(this.getShaderFile(name));
        return shader.text();
    },

    getShaderFile(url) {
        // todo: 根据脚手架获取shader文件
        const aa = url.split('/');
        let length = aa.length;
        return '/' + aa[length - 1];
    },

    img2texture(renderData = {}) {
        const {height_texture, width_texture, shape} = renderData;
        const total = height_texture * width_texture * 4;
        const b = shape[0];
        const c = shape[1];
        const h = shape[2];
        const w = shape[3];
        let data = new Float32Array(b * c * h * w * 4);
        let offset = 0;
        for (let i = 0; i < total; i++) {
            let j = (i / (c * w)) | 0;
            let k = i % (c * w);
            let b1 = j / h | 0;
            let h1 = j % h;
            let c1 = k % c;
            let w1 = k / c | 0;
            let l = b1 * (c * h * w) + c1 * (h * w) + h1 * (w) + w1;
            data[offset] = renderData.data[l];
            offset += 4;
            // data.push(renderData.data[l]);
            // data.push(0);
            // data.push(0);
            // data.push(0);
        }
        renderData.data = data;
    }
};
/* eslint-enable */
