/*
* 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'

    /**
     * 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.getDataDimension(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;