/*
* 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 env from 'zrender/src/core/env';
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
} from '../../util/types';
import ComponentModel from '../../model/Component';
import Model from '../../model/Model';
import GlobalModel from '../../model/Global';
import SeriesModel from '../../model/Series';
import List from '../../data/List';

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,
    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.
     * set min: 0, max: 200, only for campatible with ec2.
     * In fact min max should not have default value.
     */
    seriesIndex?: 'all' | number[] | number

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

    /**
     * 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?: number
}

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;

        // FIXME
        // necessary?
        // Disable realtime view update if canvas is not supported.
        if (!env.canvasSupported) {
            thisOption.realtime = false;
        }

        !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
        );
    }

    /**
     * @protected
     * @return {Array.<number>} An array of series indices.
     */
    getTargetSeriesIndices() {
        const optionSeriesIndex = this.option.seriesIndex;
        let seriesIndices: number[] = [];

        if (optionSeriesIndex == null || optionSeriesIndex === 'all') {
            this.ecModel.eachSeries(function (seriesModel, index) {
                seriesIndices.push(index);
            });
        }
        else {
            seriesIndices = modelUtil.normalizeToArray(optionSeriesIndex);
        }

        return seriesIndices;
    }

    /**
     * @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;
    }

    /**
     * Return  Concrete dimention. If return null/undefined, no dimension used.
     */
    getDataDimension(list: List) {
        const optDim = this.option.dimension;
        const listDimensions = list.dimensions;
        if (optDim == null && !listDimensions.length) {
            return;
        }

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

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

    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 defautl 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');

            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 ? 'roundRect' : ['roundRect']);
                }
                if (visuals.symbolSize == null) {
                    visuals.symbolSize = symbolSizeExists
                        && zrUtil.clone(symbolSizeExists)
                        || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]);
                }

                // Filter square and none.
                visuals.symbol = mapVisual(visuals.symbol, function (symbol) {
                    return (symbol === 'none' || symbol === 'square') ? 'roundRect' : 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: 'rgba(0,0,0,0)',
        borderColor: '#ccc',       // 值域边框颜色
        contentColor: '#5793f3',
        inactiveColor: '#aaa',
        borderWidth: 0,
        padding: 5,
                                    // 接受数组分别设定上右下左边距，同css
        textGap: 10,               //
        precision: 0,              // 小数精度，默认为0，无小数点

        textStyle: {
            color: '#333'          // 值域文字颜色
        }
    };
}

export default VisualMapModel;
