/*
* 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 * as zrColor from 'zrender/src/tool/color';
import {linearMap} from '../util/number';
import { AllPropTypes, Dictionary } from 'zrender/src/core/types';
import {
    ColorString,
    BuiltinVisualProperty,
    VisualOptionPiecewise,
    VisualOptionUnit,
    ParsedValue
} from '../util/types';
import { warn } from '../util/log';

const each = zrUtil.each;
const isObject = zrUtil.isObject;

const CATEGORY_DEFAULT_VISUAL_INDEX = -1;

// Type of raw value
type RawValue = ParsedValue;
// Type of mapping visual value
type VisualValue = AllPropTypes<VisualOptionUnit>;
// Type of value after normalized. 0 - 1
type NormalizedValue = number;

type MappingMethod = 'linear' | 'piecewise' | 'category' | 'fixed';

// May include liftZ. which is not provided to developers.

interface Normalizer {
    (this: VisualMapping, value?: RawValue): NormalizedValue
}
interface ColorMapper {
    (this: VisualMapping, value: RawValue | NormalizedValue, isNormalized?: boolean, out?: number[])
        : ColorString | number[]
}
interface DoMap {
    (this: VisualMapping, normalzied?: NormalizedValue, value?: RawValue): VisualValue
}
interface VisualValueGetter {
    (key: string): VisualValue
}
interface VisualValueSetter {
    (key: string, value: VisualValue): void
}
interface VisualHandler {
    applyVisual(
        this: VisualMapping,
        value: RawValue,
        getter: VisualValueGetter,
        setter: VisualValueSetter
    ): void

    _normalizedToVisual: {
        linear(this: VisualMapping, normalized: NormalizedValue): VisualValue
        category(this: VisualMapping, normalized: NormalizedValue): VisualValue
        piecewise(this: VisualMapping, normalzied: NormalizedValue, value: RawValue): VisualValue
        fixed(this: VisualMapping): VisualValue
    }
    /**
     * Get color mapping for the outside usage.
     * Currently only used in `color` visual.
     *
     * The last parameter out is cached color array.
     */
    getColorMapper?: (this: VisualMapping) => ColorMapper
}

interface VisualMappingPiece {
    index?: number

    value?: number | string
    interval?: [number, number]
    close?: [0 | 1, 0 | 1]

    text?: string

    visual?: VisualOptionPiecewise
}

export interface VisualMappingOption {
    type?: BuiltinVisualProperty

    mappingMethod?: MappingMethod

    /**
     * required when mappingMethod is 'linear'
     */
    dataExtent?: [number, number]
    /**
     *  required when mappingMethod is 'piecewise'.
     *  Visual for only each piece can be specified
     * [
     *   {value: someValue},
     *   {interval: [min1, max1], visual: {...}},
     *   {interval: [min2, max2]}
     *  ],.
     */
    pieceList?: VisualMappingPiece[]
    /**
     * required when mappingMethod is 'category'. If no option.categories, categories is set as [0, 1, 2, ...].
     */
    categories?: (string | number)[]
    /**
     * Whether loop mapping when mappingMethod is 'category'.
     * @default false
     */
    loop?: boolean
    /**
     * Visual data
     * when mappingMethod is 'category', visual data can be array or object
     * (like: {cate1: '#222', none: '#fff'})
     * or primary types (which represents default category visual), otherwise visual
     * can be array or primary (which will be normalized to array).
     */
    visual?: VisualValue[] | Dictionary<VisualValue> | VisualValue
}

interface VisualMappingInnerPiece extends VisualMappingPiece {
    originIndex: number
}
interface VisualMappingInnerOption extends VisualMappingOption {
    hasSpecialVisual: boolean
    pieceList: VisualMappingInnerPiece[]
    /**
     * Map to get category index
     */
    categoryMap: Dictionary<number>
    /**
     * Cached parsed rgba array from string to avoid parse every time.
     */
    parsedVisual: number[][]

    // Have converted primary value to array.
    visual?: VisualValue[] | Dictionary<VisualValue>
}

class VisualMapping {

    option: VisualMappingInnerOption;

    type: BuiltinVisualProperty;

    mappingMethod: MappingMethod;

    applyVisual: VisualHandler['applyVisual'];

    getColorMapper: VisualHandler['getColorMapper'];

    _normalizeData: Normalizer;

    _normalizedToVisual: DoMap;

    constructor(option: VisualMappingOption) {
        const mappingMethod = option.mappingMethod;
        const visualType = option.type;

        const thisOption: VisualMappingInnerOption = this.option = zrUtil.clone(option) as VisualMappingInnerOption;

        this.type = visualType;
        this.mappingMethod = mappingMethod;

        this._normalizeData = normalizers[mappingMethod];
        const visualHandler = VisualMapping.visualHandlers[visualType];

        this.applyVisual = visualHandler.applyVisual;

        this.getColorMapper = visualHandler.getColorMapper;

        this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod];

        if (mappingMethod === 'piecewise') {
            normalizeVisualRange(thisOption);
            preprocessForPiecewise(thisOption);
        }
        else if (mappingMethod === 'category') {
            thisOption.categories
                ? preprocessForSpecifiedCategory(thisOption)
                // categories is ordinal when thisOption.categories not specified,
                // which need no more preprocess except normalize visual.
                : normalizeVisualRange(thisOption, true);
        }
        else { // mappingMethod === 'linear' or 'fixed'
            zrUtil.assert(mappingMethod !== 'linear' || thisOption.dataExtent);
            normalizeVisualRange(thisOption);
        }
    }

    mapValueToVisual(value: RawValue): VisualValue {
        const normalized = this._normalizeData(value);
        return this._normalizedToVisual(normalized, value);
    }

    getNormalizer() {
        return zrUtil.bind(this._normalizeData, this);
    }

    static visualHandlers: {[key in BuiltinVisualProperty]: VisualHandler} = {
        color: {
            applyVisual: makeApplyVisual('color'),
            getColorMapper: function () {
                const thisOption = this.option;

                return zrUtil.bind(
                    thisOption.mappingMethod === 'category'
                        ? function (
                            this: VisualMapping,
                            value: NormalizedValue | RawValue,
                            isNormalized?: boolean
                        ): ColorString {
                            !isNormalized && (value = this._normalizeData(value));
                            return doMapCategory.call(this, value) as ColorString;
                        }
                        : function (
                            this: VisualMapping,
                            value: NormalizedValue | RawValue,
                            isNormalized?: boolean,
                            out?: number[]
                        ): number[] | string {
                            // If output rgb array
                            // which will be much faster and useful in pixel manipulation
                            const returnRGBArray = !!out;
                            !isNormalized && (value = this._normalizeData(value));
                            out = zrColor.fastLerp(value as NormalizedValue, thisOption.parsedVisual, out);
                            return returnRGBArray ? out : zrColor.stringify(out, 'rgba');
                        },
                    this
                );
            },

            _normalizedToVisual: {
                linear: function (normalized) {
                    return zrColor.stringify(
                        zrColor.fastLerp(normalized, this.option.parsedVisual),
                        'rgba'
                    );
                },
                category: doMapCategory,
                piecewise: function (normalized, value) {
                    let result = getSpecifiedVisual.call(this, value);
                    if (result == null) {
                        result = zrColor.stringify(
                            zrColor.fastLerp(normalized, this.option.parsedVisual),
                            'rgba'
                        );
                    }
                    return result;
                },
                fixed: doMapFixed
            }
        },

        colorHue: makePartialColorVisualHandler(function (color: ColorString, value: number) {
            return zrColor.modifyHSL(color, value);
        }),

        colorSaturation: makePartialColorVisualHandler(function (color: ColorString, value: number) {
            return zrColor.modifyHSL(color, null, value);
        }),

        colorLightness: makePartialColorVisualHandler(function (color: ColorString, value: number) {
            return zrColor.modifyHSL(color, null, null, value);
        }),

        colorAlpha: makePartialColorVisualHandler(function (color: ColorString, value: number) {
            return zrColor.modifyAlpha(color, value);
        }),

        decal: {
            applyVisual: makeApplyVisual('decal'),
            _normalizedToVisual: {
                linear: null,
                category: doMapCategory,
                piecewise: null,
                fixed: null
            }
        },

        opacity: {
            applyVisual: makeApplyVisual('opacity'),
            _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
        },

        liftZ: {
            applyVisual: makeApplyVisual('liftZ'),
            _normalizedToVisual: {
                linear: doMapFixed,
                category: doMapFixed,
                piecewise: doMapFixed,
                fixed: doMapFixed
            }
        },

        symbol: {
            applyVisual: function (value, getter, setter) {
                const symbolCfg = this.mapValueToVisual(value);
                setter('symbol', symbolCfg as string);
            },
            _normalizedToVisual: {
                linear: doMapToArray,
                category: doMapCategory,
                piecewise: function (normalized, value) {
                    let result = getSpecifiedVisual.call(this, value);
                    if (result == null) {
                        result = doMapToArray.call(this, normalized);
                    }
                    return result;
                },
                fixed: doMapFixed
            }
        },

        symbolSize: {
            applyVisual: makeApplyVisual('symbolSize'),
            _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
        }
    };


    /**
     * List available visual types.
     *
     * @public
     * @return {Array.<string>}
     */
    static listVisualTypes() {
        return zrUtil.keys(VisualMapping.visualHandlers);
    }

    // /**
    //  * @public
    //  */
    // static addVisualHandler(name, handler) {
    //     visualHandlers[name] = handler;
    // }

    /**
     * @public
     */
    static isValidType(visualType: string): boolean {
        return VisualMapping.visualHandlers.hasOwnProperty(visualType);
    }

    /**
     * Convenient method.
     * Visual can be Object or Array or primary type.
     */
    static eachVisual<Ctx, T>(
        visual: T | T[] | Dictionary<T>,
        callback: (visual: T, key?: string | number) => void,
        context?: Ctx
    ) {
        if (zrUtil.isObject(visual)) {
            zrUtil.each(visual as Dictionary<T>, callback, context);
        }
        else {
            callback.call(context, visual);
        }
    }

    static mapVisual<Ctx, T>(visual: T, callback: (visual: T, key?: string | number) => T, context?: Ctx): T;
    static mapVisual<Ctx, T>(visual: T[], callback: (visual: T, key?: string | number) => T[], context?: Ctx): T[];
    static mapVisual<Ctx, T>(
        visual: Dictionary<T>,
        callback: (visual: T, key?: string | number) => Dictionary<T>,
        context?: Ctx
    ): Dictionary<T>;
    static mapVisual<Ctx, T>(
        visual: T | T[] | Dictionary<T>,
        callback: (visual: T, key?: string | number) => T | T[] | Dictionary<T>,
        context?: Ctx
    ) {
        let isPrimary: boolean;
        let newVisual: T | T[] | Dictionary<T> = zrUtil.isArray(visual)
            ? []
            : zrUtil.isObject(visual)
            ? {}
            : (isPrimary = true, null);

        VisualMapping.eachVisual(visual, function (v, key) {
            const newVal = callback.call(context, v, key);
            isPrimary ? (newVisual = newVal) : ((newVisual as Dictionary<T>)[key as string] = newVal as T);
        });
        return newVisual;
    }

    /**
     * Retrieve visual properties from given object.
     */
    static retrieveVisuals(obj: Dictionary<any>): VisualOptionPiecewise {
        const ret: VisualOptionPiecewise = {};
        let hasVisual: boolean;

        obj && each(VisualMapping.visualHandlers, function (h, visualType: BuiltinVisualProperty) {
            if (obj.hasOwnProperty(visualType)) {
                (ret as any)[visualType] = obj[visualType];
                hasVisual = true;
            }
        });

        return hasVisual ? ret : null;
    }

    /**
     * Give order to visual types, considering colorSaturation, colorAlpha depends on color.
     *
     * @public
     * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...}
     *                                     IF Array, like: ['color', 'symbol', 'colorSaturation']
     * @return {Array.<string>} Sorted visual types.
     */
    static prepareVisualTypes(
        visualTypes: {[key in BuiltinVisualProperty]?: any} | BuiltinVisualProperty[]
    ) {
        if (zrUtil.isArray(visualTypes)) {
            visualTypes = visualTypes.slice();
        }
        else if (isObject(visualTypes)) {
            const types: BuiltinVisualProperty[] = [];
            each(visualTypes, function (item: unknown, type: BuiltinVisualProperty) {
                types.push(type);
            });
            visualTypes = types;
        }
        else {
            return [];
        }

        visualTypes.sort(function (type1: BuiltinVisualProperty, type2: BuiltinVisualProperty) {
            // color should be front of colorSaturation, colorAlpha, ...
            // symbol and symbolSize do not matter.
            return (type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0)
                ? 1 : -1;
        });

        return visualTypes;
    }

    /**
     * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'.
     * Other visuals are only depends on themself.
     */
    static dependsOn(visualType1: BuiltinVisualProperty, visualType2: BuiltinVisualProperty) {
        return visualType2 === 'color'
            ? !!(visualType1 && visualType1.indexOf(visualType2) === 0)
            : visualType1 === visualType2;
    }

    /**
     * @param value
     * @param pieceList [{value: ..., interval: [min, max]}, ...]
     *                         Always from small to big.
     * @param findClosestWhenOutside Default to be false
     * @return index
     */
    static findPieceIndex(value: number, pieceList: VisualMappingPiece[], findClosestWhenOutside?: boolean): number {
        let possibleI: number;
        let abs = Infinity;

        // value has the higher priority.
        for (let i = 0, len = pieceList.length; i < len; i++) {
            const pieceValue = pieceList[i].value;
            if (pieceValue != null) {
                if (pieceValue === value
                    // FIXME
                    // It is supposed to compare value according to value type of dimension,
                    // but currently value type can exactly be string or number.
                    // Compromise for numeric-like string (like '12'), especially
                    // in the case that visualMap.categories is ['22', '33'].
                    || (zrUtil.isString(pieceValue) && pieceValue === value + '')
                ) {
                    return i;
                }
                findClosestWhenOutside && updatePossible(pieceValue as number, i);
            }
        }

        for (let i = 0, len = pieceList.length; i < len; i++) {
            const piece = pieceList[i];
            const interval = piece.interval;
            const close = piece.close;

            if (interval) {
                if (interval[0] === -Infinity) {
                    if (littleThan(close[1], value, interval[1])) {
                        return i;
                    }
                }
                else if (interval[1] === Infinity) {
                    if (littleThan(close[0], interval[0], value)) {
                        return i;
                    }
                }
                else if (
                    littleThan(close[0], interval[0], value)
                    && littleThan(close[1], value, interval[1])
                ) {
                    return i;
                }
                findClosestWhenOutside && updatePossible(interval[0], i);
                findClosestWhenOutside && updatePossible(interval[1], i);
            }
        }

        if (findClosestWhenOutside) {
            return value === Infinity
                ? pieceList.length - 1
                : value === -Infinity
                ? 0
                : possibleI;
        }

        function updatePossible(val: number, index: number) {
            const newAbs = Math.abs(val - value);
            if (newAbs < abs) {
                abs = newAbs;
                possibleI = index;
            }
        }

    }
}

function preprocessForPiecewise(thisOption: VisualMappingInnerOption) {
    const pieceList = thisOption.pieceList;
    thisOption.hasSpecialVisual = false;

    zrUtil.each(pieceList, function (piece, index) {
        piece.originIndex = index;
        // piece.visual is "result visual value" but not
        // a visual range, so it does not need to be normalized.
        if (piece.visual != null) {
            thisOption.hasSpecialVisual = true;
        }
    });
}

function preprocessForSpecifiedCategory(thisOption: VisualMappingInnerOption) {
    // Hash categories.
    const categories = thisOption.categories;
    const categoryMap: VisualMappingInnerOption['categoryMap'] = thisOption.categoryMap = {};

    let visual = thisOption.visual;
    each(categories, function (cate, index) {
        categoryMap[cate] = index;
    });

    // Process visual map input.
    if (!zrUtil.isArray(visual)) {
        const visualArr: VisualValue[] = [];

        if (zrUtil.isObject(visual)) {
            each(visual, function (v, cate) {
                const index = categoryMap[cate];
                visualArr[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v;
            });
        }
        else { // Is primary type, represents default visual.
            visualArr[CATEGORY_DEFAULT_VISUAL_INDEX] = visual;
        }

        visual = setVisualToOption(thisOption, visualArr);
    }

    // Remove categories that has no visual,
    // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX.
    for (let i = categories.length - 1; i >= 0; i--) {
        if (visual[i] == null) {
            delete categoryMap[categories[i]];
            categories.pop();
        }
    }
}

function normalizeVisualRange(thisOption: VisualMappingInnerOption, isCategory?: boolean) {
    const visual = thisOption.visual;
    const visualArr: VisualValue[] = [];

    if (zrUtil.isObject(visual)) {
        each(visual, function (v) {
            visualArr.push(v);
        });
    }
    else if (visual != null) {
        visualArr.push(visual);
    }

    const doNotNeedPair = {color: 1, symbol: 1};

    if (!isCategory
        && visualArr.length === 1
        && !doNotNeedPair.hasOwnProperty(thisOption.type)
    ) {
        // Do not care visualArr.length === 0, which is illegal.
        visualArr[1] = visualArr[0];
    }

    setVisualToOption(thisOption, visualArr);
}

function makePartialColorVisualHandler(
    applyValue: (prop: VisualValue, value: NormalizedValue) => VisualValue
): VisualHandler {
    return {
        applyVisual: function (value, getter, setter) {
            // Only used in HSL
            const colorChannel = this.mapValueToVisual(value);
            // Must not be array value
            setter('color', applyValue(getter('color'), colorChannel as number));
        },
        _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
    };
}

function doMapToArray(this: VisualMapping, normalized: NormalizedValue): VisualValue {
    const visual = this.option.visual as VisualValue[];
    return visual[
        Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))
    ] || {} as any;    // TODO {}?
}

function makeApplyVisual(visualType: string): VisualHandler['applyVisual'] {
    return function (value, getter, setter) {
        setter(visualType, this.mapValueToVisual(value));
    };
}

function doMapCategory(this: VisualMapping, normalized: NormalizedValue): VisualValue {
    const visual = this.option.visual as Dictionary<any>;
    return visual[
        (this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX)
            ? normalized % visual.length
            : normalized
    ];
}

function doMapFixed(this: VisualMapping): VisualValue {
    // visual will be convert to array.
    return (this.option.visual as VisualValue[])[0];
}

/**
 * Create mapped to numeric visual
 */
function createNormalizedToNumericVisual(sourceExtent: [number, number]): VisualHandler['_normalizedToVisual'] {
    return {
        linear: function (normalized) {
            return linearMap(normalized, sourceExtent, this.option.visual as [number, number], true);
        },
        category: doMapCategory,
        piecewise: function (normalized, value) {
            let result = getSpecifiedVisual.call(this, value);
            if (result == null) {
                result = linearMap(normalized, sourceExtent, this.option.visual as [number, number], true);
            }
            return result;
        },
        fixed: doMapFixed
    };
}

function getSpecifiedVisual(this: VisualMapping, value: number) {
    const thisOption = this.option;
    const pieceList = thisOption.pieceList;
    if (thisOption.hasSpecialVisual) {
        const pieceIndex = VisualMapping.findPieceIndex(value, pieceList);
        const piece = pieceList[pieceIndex];
        if (piece && piece.visual) {
            return piece.visual[this.type];
        }
    }
}

function setVisualToOption(thisOption: VisualMappingInnerOption, visualArr: VisualValue[]) {
    thisOption.visual = visualArr;
    if (thisOption.type === 'color') {
        thisOption.parsedVisual = zrUtil.map(visualArr, function (item: string) {
            const color = zrColor.parse(item);
            if (!color && __DEV__) {
                warn(`'${item}' is an illegal color, fallback to '#000000'`, true);
            }
            return color || [0, 0, 0, 1];
        });
    }
    return visualArr;
}


/**
 * Normalizers by mapping methods.
 */
const normalizers: { [key in MappingMethod]: Normalizer } = {
    linear: function (value: RawValue): NormalizedValue {
        return linearMap(value as number, this.option.dataExtent, [0, 1], true);
    },

    piecewise: function (value: RawValue): NormalizedValue {
        const pieceList = this.option.pieceList;
        const pieceIndex = VisualMapping.findPieceIndex(value as number, pieceList, true);
        if (pieceIndex != null) {
            return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true);
        }
    },

    category: function (value: RawValue): NormalizedValue {
        const index: number = this.option.categories
            ? this.option.categoryMap[value]
            : value as number; // ordinal value
        return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index;
    },

    fixed: zrUtil.noop as Normalizer
};


function littleThan(close: boolean | 0 | 1, a: number, b: number): boolean {
    return close ? a <= b : a < b;
}

export default VisualMapping;
