/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import * as zrUtil from 'zrender/src/core/util';
import {parsePercent} from '../../util/number';
import type GlobalModel from '../../model/Global';
import BoxplotSeriesModel from './BoxplotSeries';
import Axis2D from '../../coord/cartesian/Axis2D';

const each = zrUtil.each;

interface GroupItem {
    seriesModels: BoxplotSeriesModel[]
    axis: Axis2D
    boxOffsetList: number[]
    boxWidthList: number[]
}

export interface BoxplotItemLayout {
    ends: number[][]
    initBaseline: number
}

export default function boxplotLayout(ecModel: GlobalModel) {

    const groupResult = groupSeriesByAxis(ecModel);

    each(groupResult, function (groupItem) {
        const seriesModels = groupItem.seriesModels;

        if (!seriesModels.length) {
            return;
        }

        calculateBase(groupItem);

        each(seriesModels, function (seriesModel, idx) {
            layoutSingleSeries(
                seriesModel,
                groupItem.boxOffsetList[idx],
                groupItem.boxWidthList[idx]
            );
        });
    });
}

/**
 * Group series by axis.
 */
function groupSeriesByAxis(ecModel: GlobalModel) {
    const result: GroupItem[] = [];
    const axisList: Axis2D[] = [];

    ecModel.eachSeriesByType('boxplot', function (seriesModel: BoxplotSeriesModel) {
        const baseAxis = seriesModel.getBaseAxis();
        let idx = zrUtil.indexOf(axisList, baseAxis);

        if (idx < 0) {
            idx = axisList.length;
            axisList[idx] = baseAxis;
            result[idx] = {
                axis: baseAxis,
                seriesModels: []
            } as GroupItem;
        }

        result[idx].seriesModels.push(seriesModel);
    });

    return result;
}

/**
 * Calculate offset and box width for each series.
 */
function calculateBase(groupItem: GroupItem) {
    const baseAxis = groupItem.axis;
    const seriesModels = groupItem.seriesModels;
    const seriesCount = seriesModels.length;

    const boxWidthList: number[] = groupItem.boxWidthList = [];
    const boxOffsetList: number[] = groupItem.boxOffsetList = [];
    const boundList: number[][] = [];

    let bandWidth: number;
    if (baseAxis.type === 'category') {
        bandWidth = baseAxis.getBandWidth();
    }
    else {
        let maxDataCount = 0;
        each(seriesModels, function (seriesModel) {
            maxDataCount = Math.max(maxDataCount, seriesModel.getData().count());
        });
        const extent = baseAxis.getExtent();
        bandWidth = Math.abs(extent[1] - extent[0]) / maxDataCount;
    }

    each(seriesModels, function (seriesModel) {
        let boxWidthBound = seriesModel.get('boxWidth');
        if (!zrUtil.isArray(boxWidthBound)) {
            boxWidthBound = [boxWidthBound, boxWidthBound];
        }
        boundList.push([
            parsePercent(boxWidthBound[0], bandWidth) || 0,
            parsePercent(boxWidthBound[1], bandWidth) || 0
        ]);
    });

    const availableWidth = bandWidth * 0.8 - 2;
    const boxGap = availableWidth / seriesCount * 0.3;
    const boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount;
    let base = boxWidth / 2 - availableWidth / 2;

    each(seriesModels, function (seriesModel, idx) {
        boxOffsetList.push(base);
        base += boxGap + boxWidth;

        boxWidthList.push(
            Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1])
        );
    });
}

/**
 * Calculate points location for each series.
 */
function layoutSingleSeries(seriesModel: BoxplotSeriesModel, offset: number, boxWidth: number) {
    const coordSys = seriesModel.coordinateSystem;
    const data = seriesModel.getData();
    const halfWidth = boxWidth / 2;
    const cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1;
    const vDimIdx = 1 - cDimIdx;
    const coordDims = ['x', 'y'];
    const cDim = data.mapDimension(coordDims[cDimIdx]);
    const vDims = data.mapDimensionsAll(coordDims[vDimIdx]);

    if (cDim == null || vDims.length < 5) {
        return;
    }

    for (let dataIndex = 0; dataIndex < data.count(); dataIndex++) {
        const axisDimVal = data.get(cDim, dataIndex) as number;

        const median = getPoint(axisDimVal, vDims[2], dataIndex);
        const end1 = getPoint(axisDimVal, vDims[0], dataIndex);
        const end2 = getPoint(axisDimVal, vDims[1], dataIndex);
        const end4 = getPoint(axisDimVal, vDims[3], dataIndex);
        const end5 = getPoint(axisDimVal, vDims[4], dataIndex);

        const ends: number[][] = [];
        addBodyEnd(ends, end2, false);
        addBodyEnd(ends, end4, true);

        ends.push(end1, end2, end5, end4);
        layEndLine(ends, end1);
        layEndLine(ends, end5);
        layEndLine(ends, median);

        data.setItemLayout(dataIndex, {
            initBaseline: median[vDimIdx],
            ends: ends
        } as BoxplotItemLayout);
    }

    function getPoint(axisDimVal: number, dim: string, dataIndex: number) {
        const val = data.get(dim, dataIndex) as number;
        const p = [];
        p[cDimIdx] = axisDimVal;
        p[vDimIdx] = val;
        let point;
        if (isNaN(axisDimVal) || isNaN(val)) {
            point = [NaN, NaN];
        }
        else {
            point = coordSys.dataToPoint(p);
            point[cDimIdx] += offset;
        }
        return point;
    }

    function addBodyEnd(ends: number[][], point: number[], start?: boolean) {
        const point1 = point.slice();
        const point2 = point.slice();
        point1[cDimIdx] += halfWidth;
        point2[cDimIdx] -= halfWidth;
        start
            ? ends.push(point1, point2)
            : ends.push(point2, point1);
    }

    function layEndLine(ends: number[][], endCenter: number[]) {
        const from = endCenter.slice();
        const to = endCenter.slice();
        from[cDimIdx] -= halfWidth;
        to[cDimIdx] += halfWidth;
        ends.push(from, to);
    }
}
