/*
* 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 VisualMapModel, { VisualMapOption, VisualMeta } from './VisualMapModel';
import VisualMapping, { VisualMappingOption } from '../../visual/VisualMapping';
import visualDefault from '../../visual/visualDefault';
import {reformIntervals} from '../../util/number';
import { VisualOptionPiecewise, BuiltinVisualProperty } from '../../util/types';
import { Dictionary } from 'zrender/src/core/types';
import { inheritDefaultOption } from '../../util/component';


// TODO: use `relationExpression.ts` instead
interface VisualPiece extends VisualOptionPiecewise {
    min?: number
    max?: number
    lt?: number
    gt?: number
    lte?: number
    gte?: number
    value?: number

    label?: string
}

type VisualState = VisualMapModel['stateList'][number];

type InnerVisualPiece = VisualMappingOption['pieceList'][number];

type GetPieceValueType<T extends InnerVisualPiece>
    = T extends { interval: InnerVisualPiece['interval'] } ? number : string;

/**
 * Order Rule:
 *
 * option.categories / option.pieces / option.text / option.selected:
 *     If !option.inverse,
 *     Order when vertical: ['top', ..., 'bottom'].
 *     Order when horizontal: ['left', ..., 'right'].
 *     If option.inverse, the meaning of
 *     the order should be reversed.
 *
 * this._pieceList:
 *     The order is always [low, ..., high].
 *
 * Mapping from location to low-high:
 *     If !option.inverse
 *     When vertical, top is high.
 *     When horizontal, right is high.
 *     If option.inverse, reverse.
 */

export interface PiecewiseVisualMapOption extends VisualMapOption {
    align?: 'auto' | 'left' | 'right'

    minOpen?: boolean
    maxOpen?: boolean

    /**
     * When put the controller vertically, it is the length of
     * horizontal side of each item. Otherwise, vertical side.
     * When put the controller vertically, it is the length of
     * vertical side of each item. Otherwise, horizontal side.
     */
    itemWidth?: number
    itemHeight?: number

    itemSymbol?: string
    pieces?: VisualPiece[]

    /**
     * category names, like: ['some1', 'some2', 'some3'].
     * Attr min/max are ignored when categories set. See "Order Rule"
     */
    categories?: string[]

    /**
     * If set to 5, auto split five pieces equally.
     * If set to 0 and component type not set, component type will be
     * determined as "continuous". (It is less reasonable but for ec2
     * compatibility, see echarts/component/visualMap/typeDefaulter)
     */
    splitNumber?: number

    /**
     * Object. If not specified, means selected. When pieces and splitNumber: {'0': true, '5': true}
     * When categories: {'cate1': false, 'cate3': true} When selected === false, means all unselected.
     */
    selected?: Dictionary<boolean>
    selectedMode?: 'multiple' | 'single' | boolean

    /**
     * By default, when text is used, label will hide (the logic
     * is remained for compatibility reason)
     */
    showLabel?: boolean

    itemGap?: number

    hoverLink?: boolean
}

class PiecewiseModel extends VisualMapModel<PiecewiseVisualMapOption> {

    static type = 'visualMap.piecewise' as const;
    type = PiecewiseModel.type;

    /**
     * The order is always [low, ..., high].
     * [{text: string, interval: Array.<number>}, ...]
     */
    private _pieceList: InnerVisualPiece[] = [];

    private _mode: 'pieces' | 'categories' | 'splitNumber';

    optionUpdated(newOption: PiecewiseVisualMapOption, isInit?: boolean) {
        super.optionUpdated.apply(this, arguments as any);

        this.resetExtent();

        const mode = this._mode = this._determineMode();

        this._pieceList = [];
        resetMethods[this._mode].call(this, this._pieceList);

        this._resetSelected(newOption, isInit);

        const categories = this.option.categories;

        this.resetVisual(function (mappingOption, state) {
            if (mode === 'categories') {
                mappingOption.mappingMethod = 'category';
                mappingOption.categories = zrUtil.clone(categories);
            }
            else {
                mappingOption.dataExtent = this.getExtent();
                mappingOption.mappingMethod = 'piecewise';
                mappingOption.pieceList = zrUtil.map(this._pieceList, function (piece) {
                    piece = zrUtil.clone(piece);
                    if (state !== 'inRange') {
                        // FIXME
                        // outOfRange do not support special visual in pieces.
                        piece.visual = null;
                    }
                    return piece;
                });
            }
        });
    }

    /**
     * @protected
     * @override
     */
    completeVisualOption() {
        // Consider this case:
        // visualMap: {
        //      pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}]
        // }
        // where no inRange/outOfRange set but only pieces. So we should make
        // default inRange/outOfRange for this case, otherwise visuals that only
        // appear in `pieces` will not be taken into account in visual encoding.

        const option = this.option;
        const visualTypesInPieces: {[key in BuiltinVisualProperty]?: 0 | 1} = {};
        const visualTypes = VisualMapping.listVisualTypes();
        const isCategory = this.isCategory();

        zrUtil.each(option.pieces, function (piece) {
            zrUtil.each(visualTypes, function (visualType: BuiltinVisualProperty) {
                if (piece.hasOwnProperty(visualType)) {
                    visualTypesInPieces[visualType] = 1;
                }
            });
        });

        zrUtil.each(visualTypesInPieces, function (v, visualType: BuiltinVisualProperty) {
            let exists = false;
            zrUtil.each(this.stateList, function (state: VisualState) {
                exists = exists || has(option, state, visualType)
                    || has(option.target, state, visualType);
            }, this);

            !exists && zrUtil.each(this.stateList, function (state: VisualState) {
                (option[state] || (option[state] = {}))[visualType] = visualDefault.get(
                    visualType, state === 'inRange' ? 'active' : 'inactive', isCategory
                );
            });
        }, this);

        function has(obj: PiecewiseVisualMapOption['target'], state: VisualState, visualType: BuiltinVisualProperty) {
            return obj && obj[state] && obj[state].hasOwnProperty(visualType);
        }

        super.completeVisualOption.apply(this, arguments as any);
    }

    private _resetSelected(newOption: PiecewiseVisualMapOption, isInit?: boolean) {
        const thisOption = this.option;
        const pieceList = this._pieceList;

        // Selected do not merge but all override.
        const selected = (isInit ? thisOption : newOption).selected || {};
        thisOption.selected = selected;

        // Consider 'not specified' means true.
        zrUtil.each(pieceList, function (piece, index) {
            const key = this.getSelectedMapKey(piece);
            if (!selected.hasOwnProperty(key)) {
                selected[key] = true;
            }
        }, this);

        if (thisOption.selectedMode === 'single') {
            // Ensure there is only one selected.
            let hasSel = false;

            zrUtil.each(pieceList, function (piece, index) {
                const key = this.getSelectedMapKey(piece);
                if (selected[key]) {
                    hasSel
                        ? (selected[key] = false)
                        : (hasSel = true);
                }
            }, this);
        }
        // thisOption.selectedMode === 'multiple', default: all selected.
    }

    /**
     * @public
     */
    getItemSymbol(): string {
        return this.get('itemSymbol');
    }

    /**
     * @public
     */
    getSelectedMapKey(piece: InnerVisualPiece) {
        return this._mode === 'categories'
            ? piece.value + '' : piece.index + '';
    }

    /**
     * @public
     */
    getPieceList(): InnerVisualPiece[] {
        return this._pieceList;
    }

    /**
     * @return {string}
     */
    private _determineMode() {
        const option = this.option;

        return option.pieces && option.pieces.length > 0
            ? 'pieces'
            : this.option.categories
            ? 'categories'
            : 'splitNumber';
    }

    /**
     * @override
     */
    setSelected(selected: this['option']['selected']) {
        this.option.selected = zrUtil.clone(selected);
    }

    /**
     * @override
     */
    getValueState(value: number): VisualState {
        const index = VisualMapping.findPieceIndex(value, this._pieceList);

        return index != null
            ? (this.option.selected[this.getSelectedMapKey(this._pieceList[index])]
                ? 'inRange' : 'outOfRange'
            )
            : 'outOfRange';
    }

    /**
     * @public
     * @param pieceIndex piece index in visualMapModel.getPieceList()
     */
    findTargetDataIndices(pieceIndex: number) {
        type DataIndices = {
            seriesId: string
            dataIndex: number[]
        };

        const result: DataIndices[] = [];
        const pieceList = this._pieceList;

        this.eachTargetSeries(function (seriesModel) {
            const dataIndices: number[] = [];
            const data = seriesModel.getData();

            data.each(this.getDataDimensionIndex(data), function (value: number, dataIndex: number) {
                // Should always base on model pieceList, because it is order sensitive.
                const pIdx = VisualMapping.findPieceIndex(value, pieceList);
                pIdx === pieceIndex && dataIndices.push(dataIndex);
            }, this);

            result.push({seriesId: seriesModel.id, dataIndex: dataIndices});
        }, this);

        return result;
    }

    /**
     * @private
     * @param piece piece.value or piece.interval is required.
     * @return  Can be Infinity or -Infinity
     */
    getRepresentValue(piece: InnerVisualPiece) {
        let representValue;
        if (this.isCategory()) {
            representValue = piece.value;
        }
        else {
            if (piece.value != null) {
                representValue = piece.value;
            }
            else {
                const pieceInterval = piece.interval || [];
                representValue = (pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity)
                    ? 0
                    : (pieceInterval[0] + pieceInterval[1]) / 2;
            }
        }

        return representValue;
    }

    getVisualMeta(
        getColorVisual: (value: number, valueState: VisualState) => string
    ): VisualMeta {
        // Do not support category. (category axis is ordinal, numerical)
        if (this.isCategory()) {
            return;
        }

        const stops: VisualMeta['stops'] = [];
        const outerColors: VisualMeta['outerColors'] = ['', ''];
        const visualMapModel = this;

        function setStop(interval: [number, number], valueState?: VisualState) {
            const representValue = visualMapModel.getRepresentValue({
                interval: interval
            }) as number;// Not category
            if (!valueState) {
                valueState = visualMapModel.getValueState(representValue);
            }
            const color = getColorVisual(representValue, valueState);
            if (interval[0] === -Infinity) {
                outerColors[0] = color;
            }
            else if (interval[1] === Infinity) {
                outerColors[1] = color;
            }
            else {
                stops.push(
                    {value: interval[0], color: color},
                    {value: interval[1], color: color}
                );
            }
        }

        // Suplement
        const pieceList = this._pieceList.slice();
        if (!pieceList.length) {
            pieceList.push({interval: [-Infinity, Infinity]});
        }
        else {
            let edge = pieceList[0].interval[0];
            edge !== -Infinity && pieceList.unshift({interval: [-Infinity, edge]});
            edge = pieceList[pieceList.length - 1].interval[1];
            edge !== Infinity && pieceList.push({interval: [edge, Infinity]});
        }

        let curr = -Infinity;
        zrUtil.each(pieceList, function (piece) {
            const interval = piece.interval;
            if (interval) {
                // Fulfill gap.
                interval[0] > curr && setStop([curr, interval[0]], 'outOfRange');
                setStop(interval.slice() as [number, number]);
                curr = interval[1];
            }
        }, this);

        return {stops: stops, outerColors: outerColors};
    }


    static defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, {
        selected: null,
        minOpen: false,             // Whether include values that smaller than `min`.
        maxOpen: false,             // Whether include values that bigger than `max`.

        align: 'auto',              // 'auto', 'left', 'right'
        itemWidth: 20,

        itemHeight: 14,

        itemSymbol: 'roundRect',
        pieces: null,
        categories: null,
        splitNumber: 5,
        selectedMode: 'multiple',   // Can be 'multiple' or 'single'.
        itemGap: 10,                // The gap between two items, in px.
        hoverLink: true             // Enable hover highlight.
    }) as PiecewiseVisualMapOption;

};

type ResetMethod = (outPieceList: InnerVisualPiece[]) => void;
/**
 * Key is this._mode
 * @type {Object}
 * @this {module:echarts/component/viusalMap/PiecewiseMode}
 */
const resetMethods: Dictionary<ResetMethod> & ThisType<PiecewiseModel> = {

    splitNumber(outPieceList) {
        const thisOption = this.option;
        let precision = Math.min(thisOption.precision, 20);
        const dataExtent = this.getExtent();
        let splitNumber = thisOption.splitNumber;
        splitNumber = Math.max(parseInt(splitNumber as unknown as string, 10), 1);
        thisOption.splitNumber = splitNumber;

        let splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber;
        // Precision auto-adaption
        while (+splitStep.toFixed(precision) !== splitStep && precision < 5) {
            precision++;
        }
        thisOption.precision = precision;
        splitStep = +splitStep.toFixed(precision);

        if (thisOption.minOpen) {
            outPieceList.push({
                interval: [-Infinity, dataExtent[0]],
                close: [0, 0]
            });
        }

        for (
            let index = 0, curr = dataExtent[0];
            index < splitNumber;
            curr += splitStep, index++
        ) {
            const max = index === splitNumber - 1 ? dataExtent[1] : (curr + splitStep);

            outPieceList.push({
                interval: [curr, max],
                close: [1, 1]
            });
        }

        if (thisOption.maxOpen) {
            outPieceList.push({
                interval: [dataExtent[1], Infinity],
                close: [0, 0]
            });
        }

        reformIntervals(outPieceList as Required<InnerVisualPiece>[]);

        zrUtil.each(outPieceList, function (piece, index) {
            piece.index = index;
            piece.text = this.formatValueText(piece.interval);
        }, this);
    },

    categories(outPieceList) {
        const thisOption = this.option;
        zrUtil.each(thisOption.categories, function (cate) {
            // FIXME category模式也使用pieceList，但在visualMapping中不是使用pieceList。
            // 是否改一致。
            outPieceList.push({
                text: this.formatValueText(cate, true),
                value: cate
            });
        }, this);

        // See "Order Rule".
        normalizeReverse(thisOption, outPieceList);
    },

    pieces(outPieceList) {
        const thisOption = this.option;

        zrUtil.each(thisOption.pieces, function (pieceListItem, index) {

            if (!zrUtil.isObject(pieceListItem)) {
                pieceListItem = {value: pieceListItem};
            }

            const item: InnerVisualPiece = {text: '', index: index};

            if (pieceListItem.label != null) {
                item.text = pieceListItem.label;
            }

            if (pieceListItem.hasOwnProperty('value')) {
                const value = item.value = pieceListItem.value;
                item.interval = [value, value];
                item.close = [1, 1];
            }
            else {
                // `min` `max` is legacy option.
                // `lt` `gt` `lte` `gte` is recommanded.
                const interval = item.interval = [] as unknown as [number, number];
                const close: typeof item.close = item.close = [0, 0];

                const closeList = [1, 0, 1] as const;
                const infinityList = [-Infinity, Infinity];

                const useMinMax = [];
                for (let lg = 0; lg < 2; lg++) {
                    const names = ([['gte', 'gt', 'min'], ['lte', 'lt', 'max']] as const)[lg];
                    for (let i = 0; i < 3 && interval[lg] == null; i++) {
                        interval[lg] = pieceListItem[names[i]];
                        close[lg] = closeList[i];
                        useMinMax[lg] = i === 2;
                    }
                    interval[lg] == null && (interval[lg] = infinityList[lg]);
                }
                useMinMax[0] && interval[1] === Infinity && (close[0] = 0);
                useMinMax[1] && interval[0] === -Infinity && (close[1] = 0);

                if (__DEV__) {
                    if (interval[0] > interval[1]) {
                        console.warn(
                            'Piece ' + index + 'is illegal: ' + interval
                            + ' lower bound should not greater then uppper bound.'
                        );
                    }
                }

                if (interval[0] === interval[1] && close[0] && close[1]) {
                    // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}],
                    // we use value to lift the priority when min === max
                    item.value = interval[0];
                }
            }

            item.visual = VisualMapping.retrieveVisuals(pieceListItem);

            outPieceList.push(item);

        }, this);

        // See "Order Rule".
        normalizeReverse(thisOption, outPieceList);
        // Only pieces
        reformIntervals(outPieceList as Required<InnerVisualPiece>[]);

        zrUtil.each(outPieceList, function (piece) {
            const close = piece.close;
            const edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]];
            piece.text = piece.text || this.formatValueText(
                piece.value != null ? piece.value : piece.interval,
                false,
                edgeSymbols
            );
        }, this);
    }
};

function normalizeReverse(thisOption: PiecewiseVisualMapOption, pieceList: InnerVisualPiece[]) {
    const inverse = thisOption.inverse;
    if (thisOption.orient === 'vertical' ? !inverse : inverse) {
            pieceList.reverse();
    }
}

export default PiecewiseModel;