/*
* 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 { each, indexOf, curry, assert, map, createHashMap } from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
import * as brushHelper from './brushHelper';
import {
    BrushPanelConfig, BrushControllerEvents, BrushType,
    BrushAreaRange, BrushDimensionMinMax
} from './BrushController';
import ExtensionAPI from '../../core/ExtensionAPI';
import GridModel from '../../coord/cartesian/GridModel';
import GeoModel from '../../coord/geo/GeoModel';
import { CoordinateSystemMaster } from '../../coord/CoordinateSystem';
import Cartesian2D from '../../coord/cartesian/Cartesian2D';
import Geo from '../../coord/geo/Geo';
import GlobalModel from '../../model/Global';
import { BrushAreaParam, BrushAreaParamInternal } from '../brush/BrushModel';
import SeriesModel from '../../model/Series';
import { Dictionary } from '../../util/types';
import {
    ModelFinderObject, ModelFinder,
    parseFinder as modelUtilParseFinder,
    ParsedModelFinderKnown
} from '../../util/model';

type COORD_CONVERTS_INDEX = 0 | 1;

// FIXME
// how to genarialize to more coordinate systems.
const INCLUDE_FINDER_MAIN_TYPES = [
    'grid', 'xAxis', 'yAxis', 'geo', 'graph',
    'polar', 'radiusAxis', 'angleAxis', 'bmap'
];

type BrushableCoordinateSystem = Cartesian2D | Geo;
type BrushTargetBuilderKey = 'grid' | 'geo';

/**
 * There can be multiple axes in a single targetInfo. Consider the case
 * of `grid` component, a targetInfo represents a grid which contains one or more
 * cartesian and one or more axes. And consider the case of parallel system,
 * which has multiple axes in a coordinate system.
 */
interface BrushTargetInfo {
    panelId: string;
    coordSysModel: CoordinateSystemMaster['model'];
    // Use the first one as the representitive coordSys.
    // A representitive cartesian in grid (first cartesian by default).
    coordSys: BrushableCoordinateSystem;
    // All cartesians.
    coordSyses: BrushableCoordinateSystem[];
    getPanelRect: GetPanelRect,
}
export interface BrushTargetInfoCartesian2D extends BrushTargetInfo {
    gridModel: GridModel;
    coordSys: Cartesian2D;
    coordSyses: Cartesian2D[];
    xAxisDeclared: boolean;
    yAxisDeclared: boolean;
}
export interface BrushTargetInfoGeo extends BrushTargetInfo {
    geoModel: GeoModel,
    coordSysModel: GeoModel,
    coordSys: Geo,
    coordSyses: Geo[],
}
type GetPanelRect = () => graphic.BoundingRect;


class BrushTargetManager {

    private _targetInfoList: BrushTargetInfo[] = [];

    /**
     * @param finder contains Index/Id/Name of xAxis/yAxis/geo/grid
     *        Each can be {number|Array.<number>}. like: {xAxisIndex: [3, 4]}
     * @param opt.include include coordinate system types.
     */
    constructor(
        finder: ModelFinderObject,
        ecModel: GlobalModel,
        opt?: {include?: BrushTargetBuilderKey[]}
    ) {
        const foundCpts = parseFinder(ecModel, finder);

        each(targetInfoBuilders, (builder, type) => {
            if (!opt || !opt.include || indexOf(opt.include, type) >= 0) {
                builder(foundCpts, this._targetInfoList);
            }
        });
    }

    setOutputRanges(
        areas: BrushControllerEvents['brush']['areas'],
        ecModel: GlobalModel
    ): BrushAreaParam[] {
        this.matchOutputRanges(areas, ecModel, function (
            area: BrushAreaParam,
            coordRange: ReturnType<ConvertCoord>['values'],
            coordSys: BrushableCoordinateSystem
        ) {
            (area.coordRanges || (area.coordRanges = [])).push(coordRange);
            // area.coordRange is the first of area.coordRanges
            if (!area.coordRange) {
                area.coordRange = coordRange;
                // In 'category' axis, coord to pixel is not reversible, so we can not
                // rebuild range by coordRange accrately, which may bring trouble when
                // brushing only one item. So we use __rangeOffset to rebuilding range
                // by coordRange. And this it only used in brush component so it is no
                // need to be adapted to coordRanges.
                const result = coordConvert[area.brushType](0, coordSys, coordRange);
                area.__rangeOffset = {
                    offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]),
                    xyMinMax: result.xyMinMax
                };
            }
        });
        return areas;
    }

    matchOutputRanges<T extends (
        Parameters<BrushTargetManager['findTargetInfo']>[0] & {
            brushType: BrushType;
            range: BrushAreaRange;
        }
    )>(
        areas: T[],
        ecModel: GlobalModel,
        cb: (
            area: T,
            coordRange: ReturnType<ConvertCoord>['values'],
            coordSys: BrushableCoordinateSystem,
            ecModel: GlobalModel
        ) => void
    ) {
        each(areas, function (area) {
            const targetInfo = this.findTargetInfo(area, ecModel);

            if (targetInfo && targetInfo !== true) {
                each(
                    targetInfo.coordSyses,
                    function (coordSys) {
                        const result = coordConvert[area.brushType](1, coordSys, area.range, true);
                        cb(area, result.values, coordSys, ecModel);
                    }
                );
            }
        }, this);
    }

    /**
     * the `areas` is `BrushModel.areas`.
     * Called in layout stage.
     * convert `area.coordRange` to global range and set panelId to `area.range`.
     */
    setInputRanges(
        areas: BrushAreaParamInternal[],
        ecModel: GlobalModel
    ): void {
        each(areas, function (area) {
            const targetInfo = this.findTargetInfo(area, ecModel);

            if (__DEV__) {
                assert(
                    !targetInfo || targetInfo === true || area.coordRange,
                    'coordRange must be specified when coord index specified.'
                );
                assert(
                    !targetInfo || targetInfo !== true || area.range,
                    'range must be specified in global brush.'
                );
            }

            area.range = area.range || [];

            // convert coordRange to global range and set panelId.
            if (targetInfo && targetInfo !== true) {
                area.panelId = targetInfo.panelId;
                // (1) area.range shoule always be calculate from coordRange but does
                // not keep its original value, for the sake of the dataZoom scenario,
                // where area.coordRange remains unchanged but area.range may be changed.
                // (2) Only support converting one coordRange to pixel range in brush
                // component. So do not consider `coordRanges`.
                // (3) About __rangeOffset, see comment above.
                const result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange);
                const rangeOffset = area.__rangeOffset;
                area.range = rangeOffset
                    ? diffProcessor[area.brushType](
                        result.values,
                        rangeOffset.offset,
                        getScales(result.xyMinMax, rangeOffset.xyMinMax)
                    )
                    : result.values;
            }
        }, this);
    }

    makePanelOpts(
        api: ExtensionAPI,
        getDefaultBrushType?: (targetInfo: BrushTargetInfo) => BrushType
    ): BrushPanelConfig[] {
        return map(this._targetInfoList, function (targetInfo) {
            const rect = targetInfo.getPanelRect();
            return {
                panelId: targetInfo.panelId,
                defaultBrushType: getDefaultBrushType ? getDefaultBrushType(targetInfo) : null,
                clipPath: brushHelper.makeRectPanelClipPath(rect),
                isTargetByCursor: brushHelper.makeRectIsTargetByCursor(
                    rect, api, targetInfo.coordSysModel
                ),
                getLinearBrushOtherExtent: brushHelper.makeLinearBrushOtherExtent(rect)
            };
        });
    }

    controlSeries(area: BrushAreaParamInternal, seriesModel: SeriesModel, ecModel: GlobalModel): boolean {
        // Check whether area is bound in coord, and series do not belong to that coord.
        // If do not do this check, some brush (like lineX) will controll all axes.
        const targetInfo = this.findTargetInfo(area, ecModel);
        return targetInfo === true || (
            targetInfo && indexOf(
                targetInfo.coordSyses, seriesModel.coordinateSystem as BrushableCoordinateSystem
            ) >= 0
        );
    }

    /**
     * If return Object, a coord found.
     * If reutrn true, global found.
     * Otherwise nothing found.
     */
    findTargetInfo(
        area: ModelFinderObject & {
            panelId?: string
        },
        ecModel: GlobalModel
    ): BrushTargetInfo | true {
        const targetInfoList = this._targetInfoList;
        const foundCpts = parseFinder(ecModel, area);

        for (let i = 0; i < targetInfoList.length; i++) {
            const targetInfo = targetInfoList[i];
            const areaPanelId = area.panelId;
            if (areaPanelId) {
                if (targetInfo.panelId === areaPanelId) {
                    return targetInfo;
                }
            }
            else {
                for (let j = 0; j < targetInfoMatchers.length; j++) {
                    if (targetInfoMatchers[j](foundCpts, targetInfo)) {
                        return targetInfo;
                    }
                }
            }
        }

        return true;
    }

}

function formatMinMax(minMax: BrushDimensionMinMax): BrushDimensionMinMax {
    minMax[0] > minMax[1] && minMax.reverse();
    return minMax;
}

function parseFinder(
    ecModel: GlobalModel, finder: ModelFinder
): ParsedModelFinderKnown {
    return modelUtilParseFinder(
        ecModel, finder, {includeMainTypes: INCLUDE_FINDER_MAIN_TYPES}
    );
}

type TargetInfoBuilder = (
    foundCpts: ParsedModelFinderKnown, targetInfoList: BrushTargetInfo[]
) => void;
const targetInfoBuilders: Record<BrushTargetBuilderKey, TargetInfoBuilder> = {

    grid: function (foundCpts, targetInfoList) {
        const xAxisModels = foundCpts.xAxisModels;
        const yAxisModels = foundCpts.yAxisModels;
        const gridModels = foundCpts.gridModels;
        // Remove duplicated.
        const gridModelMap = createHashMap<GridModel>();
        const xAxesHas = {} as Dictionary<boolean>;
        const yAxesHas = {} as Dictionary<boolean>;

        if (!xAxisModels && !yAxisModels && !gridModels) {
            return;
        }

        each(xAxisModels, function (axisModel) {
            const gridModel = axisModel.axis.grid.model;
            gridModelMap.set(gridModel.id, gridModel);
            xAxesHas[gridModel.id] = true;
        });
        each(yAxisModels, function (axisModel) {
            const gridModel = axisModel.axis.grid.model;
            gridModelMap.set(gridModel.id, gridModel);
            yAxesHas[gridModel.id] = true;
        });
        each(gridModels, function (gridModel) {
            gridModelMap.set(gridModel.id, gridModel);
            xAxesHas[gridModel.id] = true;
            yAxesHas[gridModel.id] = true;
        });

        gridModelMap.each(function (gridModel) {
            const grid = gridModel.coordinateSystem;
            const cartesians = [] as Cartesian2D[];

            each(grid.getCartesians(), function (cartesian, index) {
                if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0
                    || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0
                ) {
                    cartesians.push(cartesian);
                }
            });
            targetInfoList.push({
                panelId: 'grid--' + gridModel.id,
                gridModel: gridModel,
                coordSysModel: gridModel,
                // Use the first one as the representitive coordSys.
                coordSys: cartesians[0],
                coordSyses: cartesians,
                getPanelRect: panelRectBuilders.grid,
                xAxisDeclared: xAxesHas[gridModel.id],
                yAxisDeclared: yAxesHas[gridModel.id]
            } as BrushTargetInfoCartesian2D);
        });
    },

    geo: function (foundCpts, targetInfoList) {
        each(foundCpts.geoModels, function (geoModel: GeoModel) {
            const coordSys = geoModel.coordinateSystem;
            targetInfoList.push({
                panelId: 'geo--' + geoModel.id,
                geoModel: geoModel,
                coordSysModel: geoModel,
                coordSys: coordSys,
                coordSyses: [coordSys],
                getPanelRect: panelRectBuilders.geo
            } as BrushTargetInfoGeo);
        });
    }
};

type TargetInfoMatcher = (
    foundCpts: ParsedModelFinderKnown, targetInfo: BrushTargetInfo
) => boolean;
const targetInfoMatchers: TargetInfoMatcher[] = [

    // grid
    function (foundCpts, targetInfo) {
        const xAxisModel = foundCpts.xAxisModel;
        const yAxisModel = foundCpts.yAxisModel;
        let gridModel = foundCpts.gridModel;

        !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model);
        !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model);

        return gridModel && gridModel === (targetInfo as BrushTargetInfoCartesian2D).gridModel;
    },

    // geo
    function (foundCpts, targetInfo) {
        const geoModel = foundCpts.geoModel;
        return geoModel && geoModel === (targetInfo as BrushTargetInfoGeo).geoModel;
    }
];

type PanelRectBuilder = (this: BrushTargetInfo) => graphic.BoundingRect;
const panelRectBuilders: Record<BrushTargetBuilderKey, PanelRectBuilder> = {

    grid: function (this: BrushTargetInfoCartesian2D) {
        // grid is not Transformable.
        return this.coordSys.master.getRect().clone();
    },

    geo: function (this: BrushTargetInfoGeo) {
        const coordSys = this.coordSys;
        const rect = coordSys.getBoundingRect().clone();
        // geo roam and zoom transform
        rect.applyTransform(graphic.getTransform(coordSys));
        return rect;
    }
};

type ConvertCoord = (
    to: COORD_CONVERTS_INDEX,
    coordSys: BrushableCoordinateSystem,
    rangeOrCoordRange: BrushAreaRange,
    clamp?: boolean
) => {
    values: BrushAreaRange,
    xyMinMax: BrushDimensionMinMax[]
};
const coordConvert: Record<BrushType, ConvertCoord> = {

    lineX: curry(axisConvert, 0),

    lineY: curry(axisConvert, 1),

    rect: function (to, coordSys, rangeOrCoordRange: BrushDimensionMinMax[], clamp): {
        values: BrushDimensionMinMax[],
        xyMinMax: BrushDimensionMinMax[]
    } {
        const xminymin = to
            ? coordSys.pointToData([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]], clamp)
            : coordSys.dataToPoint([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]], clamp);
        const xmaxymax = to
            ? coordSys.pointToData([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]], clamp)
            : coordSys.dataToPoint([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]], clamp);
        const values = [
            formatMinMax([xminymin[0], xmaxymax[0]]),
            formatMinMax([xminymin[1], xmaxymax[1]])
        ];
        return {values: values, xyMinMax: values};
    },

    polygon: function (to, coordSys, rangeOrCoordRange: BrushDimensionMinMax[], clamp): {
        values: BrushDimensionMinMax[],
        xyMinMax: BrushDimensionMinMax[]
    } {
        const xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]];
        const values = map(rangeOrCoordRange, function (item) {
            const p = to ? coordSys.pointToData(item, clamp) : coordSys.dataToPoint(item, clamp);
            xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]);
            xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]);
            xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]);
            xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]);
            return p;
        });
        return {values: values, xyMinMax: xyMinMax};
    }
};

function axisConvert(
    axisNameIndex: 0 | 1,
    to: COORD_CONVERTS_INDEX,
    coordSys: Cartesian2D,
    rangeOrCoordRange: BrushDimensionMinMax
): {
    values: BrushDimensionMinMax,
    xyMinMax: BrushDimensionMinMax[]
} {
    if (__DEV__) {
        assert(
            coordSys.type === 'cartesian2d',
            'lineX/lineY brush is available only in cartesian2d.'
        );
    }

    const axis = coordSys.getAxis(['x', 'y'][axisNameIndex]);
    const values = formatMinMax(map([0, 1], function (i) {
        return to
            ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i]), true)
            : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i]));
    }));
    const xyMinMax = [];
    xyMinMax[axisNameIndex] = values;
    xyMinMax[1 - axisNameIndex] = [NaN, NaN];

    return {values: values, xyMinMax: xyMinMax};
}


type DiffProcess = (
    values: BrushDimensionMinMax | BrushDimensionMinMax[],
    refer: BrushDimensionMinMax | BrushDimensionMinMax[],
    scales: ReturnType<typeof getScales>
) => BrushDimensionMinMax | BrushDimensionMinMax[];

const diffProcessor: Record<BrushType, DiffProcess> = {

    lineX: curry(axisDiffProcessor, 0),

    lineY: curry(axisDiffProcessor, 1),

    rect: function (
        values: BrushDimensionMinMax[], refer: BrushDimensionMinMax[], scales: ReturnType<typeof getScales>
    ): BrushDimensionMinMax[] {
        return [
            [values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]],
            [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]
        ];
    },

    polygon: function (
        values: BrushDimensionMinMax[], refer: BrushDimensionMinMax[], scales: ReturnType<typeof getScales>
    ): BrushDimensionMinMax[] {
        return map(values, function (item, idx) {
            return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]];
        });
    }
};

function axisDiffProcessor(
    axisNameIndex: 0 | 1,
    values: BrushDimensionMinMax,
    refer: BrushDimensionMinMax,
    scales: ReturnType<typeof getScales>
): BrushDimensionMinMax {
    return [
        values[0] - scales[axisNameIndex] * refer[0],
        values[1] - scales[axisNameIndex] * refer[1]
    ];
}

// We have to process scale caused by dataZoom manually,
// although it might be not accurate.
// Return [0~1, 0~1]
function getScales(xyMinMaxCurr: BrushDimensionMinMax[], xyMinMaxOrigin: BrushDimensionMinMax[]): number[] {
    const sizeCurr = getSize(xyMinMaxCurr);
    const sizeOrigin = getSize(xyMinMaxOrigin);
    const scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]];
    isNaN(scales[0]) && (scales[0] = 1);
    isNaN(scales[1]) && (scales[1] = 1);
    return scales;
}

function getSize(xyMinMax: BrushDimensionMinMax[]): number[] {
    return xyMinMax
        ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]]
        : [NaN, NaN];
}

export default BrushTargetManager;
