/*
* 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 visualDefault from '../../visual/visualDefault';
import VisualMapping, { VisualMappingOption } from '../../visual/VisualMapping';
import * as visualSolution from '../../visual/visualSolution';
import * as modelUtil from '../../util/model';
import * as numberUtil from '../../util/number';
import {
    ComponentOption,
    BoxLayoutOptionMixin,
    LabelOption,
    ColorString,
    ZRColor,
    BorderOptionMixin,
    OptionDataValue,
    BuiltinVisualProperty,
    DimensionIndex,
    ComponentOnCalendarOptionMixin,
    ComponentOnMatrixOptionMixin,
    OptionId,
} from '../../util/types';
import ComponentModel from '../../model/Component';
import Model from '../../model/Model';
import GlobalModel from '../../model/Global';
import SeriesModel from '../../model/Series';
import SeriesData from '../../data/SeriesData';
import tokens from '../../visual/tokens';

const mapVisual = VisualMapping.mapVisual;
const eachVisual = VisualMapping.eachVisual;
const isArray = zrUtil.isArray;
const each = zrUtil.each;
const asc = numberUtil.asc;
const linearMap = numberUtil.linearMap;

type VisualOptionBase = {[key in BuiltinVisualProperty]?: any};

type LabelFormatter = (min: OptionDataValue, max?: OptionDataValue) => string;

type VisualState = VisualMapModel['stateList'][number];
export interface VisualMapOption<T extends VisualOptionBase = VisualOptionBase> extends
    ComponentOption,
    ComponentOnCalendarOptionMixin,
    ComponentOnMatrixOptionMixin,
    BoxLayoutOptionMixin,
    BorderOptionMixin {

    mainType?: 'visualMap'

    show?: boolean

    align?: string

    realtime?: boolean
    /**
     * 'all' or null/undefined: all series.
     * A number or an array of number: the specified series.
     */
    seriesIndex?: modelUtil.ModelFinderIndexQuery
    seriesId?: modelUtil.ModelFinderIdQuery

    /**
     * set min: 0, max: 200, only for campatible with ec2.
     * In fact min max should not have default value.
     * min value, must specified if pieces is not specified.
     */
    min?: number

    /**
     * max value, must specified if pieces is not specified.
     */
    max?: number
    /**
     * Dimension to be encoded
     */
    dimension?: number

    /**
     * Series targets with specific dimensions
     * When provided, seriesIndex, seriesId, and dimension are ignored
     */
    seriesTargets?: {
        seriesIndex?: number
        seriesId?: OptionId
        dimension: number
    }[]

    /**
     * Visual configuration for the data in selection
     */
    inRange?: T
    /**
     * Visual configuration for the out of selection
     */
    outOfRange?: T

    controller?: {
        inRange?: T
        outOfRange?: T
    }
    target?: {
        inRange?: T
        outOfRange?: T
    }

    /**
     * Width of the display item
     */
    itemWidth?: number
    /**
     * Height of the display item
     */
    itemHeight?: number

    inverse?: boolean

    orient?: 'horizontal' | 'vertical'

    backgroundColor?: ZRColor
    contentColor?: ZRColor

    inactiveColor?: ZRColor

    /**
     * Padding of the component. Can be an array similar to CSS
     */
    padding?: number[] | number
    /**
     * Gap between text and item
     */
    textGap?: number

    precision?: number

    /**
     * @deprecated
     * Option from version 2
     */
    color?: ColorString[]

    formatter?: string | LabelFormatter

    /**
     * Text on the both end. Such as ['High', 'Low']
     */
    text?: string[]

    textStyle?: LabelOption


    categories?: unknown
}

export interface VisualMeta {
    stops: { value: number, color: ColorString}[]
    outerColors: ColorString[]

    dimension?: DimensionIndex
}

class VisualMapModel<Opts extends VisualMapOption = VisualMapOption> extends ComponentModel<Opts> {

    static type = 'visualMap';
    type = VisualMapModel.type;

    static readonly dependencies = ['series'];

    readonly stateList = ['inRange', 'outOfRange'] as const;

    readonly replacableOptionKeys = [
        'inRange', 'outOfRange', 'target', 'controller', 'color'
    ] as const;

    readonly layoutMode = {
        type: 'box', ignoreSize: true
    } as const;

    /**
     * [lowerBound, upperBound]
     */
    dataBound = [-Infinity, Infinity];

    protected _dataExtent: [number, number];

    targetVisuals = {} as ReturnType<typeof visualSolution.createVisualMappings>;

    controllerVisuals = {} as ReturnType<typeof visualSolution.createVisualMappings>;

    textStyleModel: Model<LabelOption>;

    itemSize: number[];

    init(option: Opts, parentModel: Model, ecModel: GlobalModel) {
        this.mergeDefaultAndTheme(option, ecModel);
    }

    /**
     * @protected
     */
    optionUpdated(newOption: Opts, isInit?: boolean) {
        const thisOption = this.option;

        !isInit && visualSolution.replaceVisualOption(
            thisOption, newOption, this.replacableOptionKeys
        );

        this.textStyleModel = this.getModel('textStyle');

        this.resetItemSize();

        this.completeVisualOption();
    }

    /**
     * @protected
     */
    resetVisual(
        supplementVisualOption: (this: this, mappingOption: VisualMappingOption, state: string) => void
    ) {
        const stateList = this.stateList;
        supplementVisualOption = zrUtil.bind(supplementVisualOption, this);

        this.controllerVisuals = visualSolution.createVisualMappings(
            this.option.controller, stateList, supplementVisualOption
        );
        this.targetVisuals = visualSolution.createVisualMappings(
            this.option.target, stateList, supplementVisualOption
        );
    }

    /**
     * @public
     */
    getItemSymbol(): string {
        return null;
    }

    /**
     * @return An array of series indices.
     */
    protected getTargetSeriesIndices(): number[] {
        const seriesTargets = this.option.seriesTargets;
        if (seriesTargets) {
            // When seriesTargets is provided, collect all target series indices
            const indices: number[] = [];
            each(seriesTargets, (target) => {
                if (target.seriesIndex != null) {
                    indices.push(target.seriesIndex);
                }
                else if (target.seriesId != null) {
                    // Find series by ID
                    let seriesModel: SeriesModel;
                    this.ecModel.eachSeries(function (series) {
                        if (series.id === target.seriesId) {
                            seriesModel = series;
                        }
                    });
                    if (seriesModel) {
                        indices.push(seriesModel.componentIndex);
                    }
                }
            });
            return indices;
        }

        const optionSeriesId = this.option.seriesId;
        let optionSeriesIndex = this.option.seriesIndex;
        if (optionSeriesIndex == null && optionSeriesId == null) {
            optionSeriesIndex = 'all';
        }

        const seriesModels = modelUtil.queryReferringComponents(
            this.ecModel,
            'series',
            {
                index: optionSeriesIndex,
                id: optionSeriesId,
            },
            {
                useDefault: false,
                enableAll: true,
                enableNone: false,
            }
        ).models;

        return zrUtil.map(seriesModels, seriesModel => seriesModel.componentIndex);
    }

    /**
     * @public
     */
    eachTargetSeries<Ctx>(
        callback: (this: Ctx, series: SeriesModel) => void,
        context?: Ctx
    ) {
        zrUtil.each(this.getTargetSeriesIndices(), function (seriesIndex) {
            const seriesModel = this.ecModel.getSeriesByIndex(seriesIndex);
            if (seriesModel) {
                callback.call(context, seriesModel);
            }
        }, this);
    }

    /**
     * @pubilc
     */
    isTargetSeries(seriesModel: SeriesModel) {
        let is = false;
        this.eachTargetSeries(function (model) {
            model === seriesModel && (is = true);
        });
        return is;
    }

    /**
     * @example
     * this.formatValueText(someVal); // format single numeric value to text.
     * this.formatValueText(someVal, true); // format single category value to text.
     * this.formatValueText([min, max]); // format numeric min-max to text.
     * this.formatValueText([this.dataBound[0], max]); // using data lower bound.
     * this.formatValueText([min, this.dataBound[1]]); // using data upper bound.
     *
     * @param value Real value, or this.dataBound[0 or 1].
     * @param isCategory Only available when value is number.
     * @param edgeSymbols Open-close symbol when value is interval.
     * @protected
     */
    formatValueText(
        value: number | string | number[],
        isCategory?: boolean,
        edgeSymbols?: string[]
    ): string {
        const option = this.option;
        const precision = option.precision;
        const dataBound = this.dataBound;
        const formatter = option.formatter;
        let isMinMax: boolean;
        edgeSymbols = edgeSymbols || ['<', '>'] as [string, string];

        if (zrUtil.isArray(value)) {
            value = value.slice();
            isMinMax = true;
        }

        const textValue = isCategory
            ? value as string   // Value is string when isCategory
            : (isMinMax
                ? [toFixed((value as number[])[0]), toFixed((value as number[])[1])]
                : toFixed(value as number)
            );

        if (zrUtil.isString(formatter)) {
            return formatter
                .replace('{value}', isMinMax ? (textValue as string[])[0] : textValue as string)
                .replace('{value2}', isMinMax ? (textValue as string[])[1] : textValue as string);
        }
        else if (zrUtil.isFunction(formatter)) {
            return isMinMax
                ? formatter((value as number[])[0], (value as number[])[1])
                : formatter(value as number);
        }

        if (isMinMax) {
            if ((value as number[])[0] === dataBound[0]) {
                return edgeSymbols[0] + ' ' + textValue[1];
            }
            else if ((value as number[])[1] === dataBound[1]) {
                return edgeSymbols[1] + ' ' + textValue[0];
            }
            else {
                return textValue[0] + ' - ' + textValue[1];
            }
        }
        else { // Format single value (includes category case).
            return textValue as string;
        }

        function toFixed(val: number) {
            return val === dataBound[0]
                ? 'min'
                : val === dataBound[1]
                ? 'max'
                : (+val).toFixed(Math.min(precision, 20));
        }
    }

    /**
     * @protected
     */
    resetExtent() {
        const thisOption = this.option;

        // Can not calculate data extent by data here.
        // Because series and data may be modified in processing stage.
        // So we do not support the feature "auto min/max".

        const extent = asc([thisOption.min, thisOption.max] as [number, number]);

        this._dataExtent = extent;
    }

    /**
     * PENDING:
     * delete this method if no outer usage.
     *
     * Return  Concrete dimension. If null/undefined is returned, no dimension is used.
     */
    // getDataDimension(data: SeriesData) {
    //     const optDim = this.option.dimension;

    //     if (optDim != null) {
    //         return data.getDimension(optDim);
    //     }

    //     const dimNames = data.dimensions;
    //     for (let i = dimNames.length - 1; i >= 0; i--) {
    //         const dimName = dimNames[i];
    //         const dimInfo = data.getDimensionInfo(dimName);
    //         if (!dimInfo.isCalculationCoord) {
    //             return dimName;
    //         }
    //     }
    // }

    getDimension(seriesIndex: number): number {
        const seriesTargets = this.option.seriesTargets;
        if (seriesTargets) {
            const target = zrUtil.find(seriesTargets, target =>
                (target.seriesIndex != null && target.seriesIndex === seriesIndex)
                || (target.seriesId != null && target.seriesId === this.ecModel.getSeriesByIndex(seriesIndex).id)
            );
            if (target) {
                return target.dimension;
            }
        }
        return this.option.dimension;
    }

    getDataDimensionIndex(data: SeriesData): DimensionIndex {
        const seriesIndex = (data.hostModel as any).seriesIndex;
        const optDim = this.getDimension(seriesIndex);

        if (optDim != null) {
            return data.getDimensionIndex(optDim);
        }

        const dimNames = data.dimensions;
        for (let i = dimNames.length - 1; i >= 0; i--) {
            const dimName = dimNames[i];
            const dimInfo = data.getDimensionInfo(dimName);
            if (!dimInfo.isCalculationCoord) {
                return dimInfo.storeDimIndex;
            }
        }
    }

    getExtent() {
        return this._dataExtent.slice() as [number, number];
    }

    completeVisualOption() {

        const ecModel = this.ecModel;
        const thisOption = this.option;
        const base = {
            inRange: thisOption.inRange,
            outOfRange: thisOption.outOfRange
        };

        const target = thisOption.target || (thisOption.target = {});
        const controller = thisOption.controller || (thisOption.controller = {});

        zrUtil.merge(target, base); // Do not override
        zrUtil.merge(controller, base); // Do not override

        const isCategory = this.isCategory();

        completeSingle.call(this, target);
        completeSingle.call(this, controller);
        completeInactive.call(this, target, 'inRange', 'outOfRange');
        // completeInactive.call(this, target, 'outOfRange', 'inRange');
        completeController.call(this, controller);

        function completeSingle(this: VisualMapModel, base: VisualMapOption['target']) {
            // Compatible with ec2 dataRange.color.
            // The mapping order of dataRange.color is: [high value, ..., low value]
            // whereas inRange.color and outOfRange.color is [low value, ..., high value]
            // Notice: ec2 has no inverse.
            if (isArray(thisOption.color)
                // If there has been inRange: {symbol: ...}, adding color is a mistake.
                // So adding color only when no inRange defined.
                && !base.inRange
            ) {
                base.inRange = {color: thisOption.color.slice().reverse()};
            }

            // Compatible with previous logic, always give a default color, otherwise
            // simple config with no inRange and outOfRange will not work.
            // Originally we use visualMap.color as the default color, but setOption at
            // the second time the default color will be erased. So we change to use
            // constant DEFAULT_COLOR.
            // If user do not want the default color, set inRange: {color: null}.
            base.inRange = base.inRange || {color: ecModel.get('gradientColor')};
        }

        function completeInactive(
            this: VisualMapModel,
            base: VisualMapOption['target'],
            stateExist: VisualState,
            stateAbsent: VisualState
        ) {
            const optExist = base[stateExist];
            let optAbsent = base[stateAbsent];

            if (optExist && !optAbsent) {
                optAbsent = base[stateAbsent] = {};
                each(optExist, function (visualData, visualType: BuiltinVisualProperty) {
                    if (!VisualMapping.isValidType(visualType)) {
                        return;
                    }

                    const defa = visualDefault.get(visualType, 'inactive', isCategory);

                    if (defa != null) {
                        optAbsent[visualType] = defa;

                        // Compatibable with ec2:
                        // Only inactive color to rgba(0,0,0,0) can not
                        // make label transparent, so use opacity also.
                        if (visualType === 'color'
                            && !optAbsent.hasOwnProperty('opacity')
                            && !optAbsent.hasOwnProperty('colorAlpha')
                        ) {
                            optAbsent.opacity = [0, 0];
                        }
                    }
                });
            }
        }

        function completeController(this: VisualMapModel, controller?: VisualMapOption['controller']) {
            const symbolExists = (controller.inRange || {}).symbol
                || (controller.outOfRange || {}).symbol;
            const symbolSizeExists = (controller.inRange || {}).symbolSize
                || (controller.outOfRange || {}).symbolSize;
            const inactiveColor = this.get('inactiveColor');
            const itemSymbol = this.getItemSymbol();
            const defaultSymbol = itemSymbol || 'roundRect';

            each(this.stateList, function (state: VisualState) {

                const itemSize = this.itemSize;
                let visuals = controller[state];

                // Set inactive color for controller if no other color
                // attr (like colorAlpha) specified.
                if (!visuals) {
                    visuals = controller[state] = {
                        color: isCategory ? inactiveColor : [inactiveColor]
                    };
                }

                // Consistent symbol and symbolSize if not specified.
                if (visuals.symbol == null) {
                    visuals.symbol = symbolExists
                        && zrUtil.clone(symbolExists)
                        || (isCategory ? defaultSymbol : [defaultSymbol]);
                }
                if (visuals.symbolSize == null) {
                    visuals.symbolSize = symbolSizeExists
                        && zrUtil.clone(symbolSizeExists)
                        || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]);
                }

                // Filter none
                visuals.symbol = mapVisual(visuals.symbol, function (symbol) {
                    return symbol === 'none' ? defaultSymbol : symbol;
                });

                // Normalize symbolSize
                const symbolSize = visuals.symbolSize;

                if (symbolSize != null) {
                    let max = -Infinity;
                    // symbolSize can be object when categories defined.
                    eachVisual(symbolSize, function (value) {
                        value > max && (max = value);
                    });
                    visuals.symbolSize = mapVisual(symbolSize, function (value) {
                        return linearMap(value, [0, max], [0, itemSize[0]], true);
                    });
                }

            }, this);
        }
    }

    resetItemSize() {
        this.itemSize = [
            parseFloat(this.get('itemWidth') as unknown as string),
            parseFloat(this.get('itemHeight') as unknown as string)
        ];
    }

    isCategory() {
        return !!this.option.categories;
    }

    /**
     * @public
     * @abstract
     */
    setSelected(selected?: any) {}

    getSelected(): any {
        return null;
    }

    /**
     * @public
     * @abstract
     */
    getValueState(value: any): VisualMapModel['stateList'][number] {
        return null;
    }

    /**
     * FIXME
     * Do not publish to thirt-part-dev temporarily
     * util the interface is stable. (Should it return
     * a function but not visual meta?)
     *
     * @pubilc
     * @abstract
     * @param getColorVisual
     *        params: value, valueState
     *        return: color
     * @return {Object} visualMeta
     *        should includes {stops, outerColors}
     *        outerColor means [colorBeyondMinValue, colorBeyondMaxValue]
     */
    getVisualMeta(getColorVisual: (value: number, valueState: VisualState) => string): VisualMeta {
        return null;
    }


    static defaultOption: VisualMapOption = {
        show: true,

        // zlevel: 0,
        z: 4,

        // seriesIndex: 'all',

        min: 0,
        max: 200,

        left: 0,
        right: null,
        top: null,
        bottom: 0,

        itemWidth: null,
        itemHeight: null,
        inverse: false,
        orient: 'vertical',        // 'horizontal' ¦ 'vertical'

        backgroundColor: tokens.color.transparent,
        borderColor: tokens.color.borderTint,       // 值域边框颜色
        contentColor: tokens.color.theme[0],
        inactiveColor: tokens.color.disabled,
        borderWidth: 0,
        padding: tokens.size.m,
                                    // 接受数组分别设定上右下左边距，同css
        textGap: 10,               //
        precision: 0,              // 小数精度，默认为0，无小数点

        textStyle: {
            color: tokens.color.secondary          // 值域文字颜色
        }
    };
}

export default VisualMapModel;
