/*
* 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 {
    each,
    isObject,
    isArray,
    createHashMap,
    HashMap,
    map,
    assert,
    isString,
    indexOf,
    isStringSafe
} from 'zrender/src/core/util';
import env from 'zrender/src/core/env';
import GlobalModel from '../model/Global';
import ComponentModel, {ComponentModelConstructor} from '../model/Component';
import List from '../data/List';
import {
    ComponentOption,
    ComponentMainType,
    ComponentSubType,
    DisplayStateHostOption,
    OptionDataItem,
    OptionDataValue,
    TooltipRenderMode,
    Payload,
    OptionId,
    OptionName,
    InterpolatableValue
} from './types';
import { Dictionary } from 'zrender/src/core/types';
import SeriesModel from '../model/Series';
import CartesianAxisModel from '../coord/cartesian/AxisModel';
import GridModel from '../coord/cartesian/GridModel';
import { isNumeric, getRandomIdBase, getPrecision, round } from './number';
import { interpolateNumber } from 'zrender/src/animation/Animator';
import { warn } from './log';

/**
 * Make the name displayable. But we should
 * make sure it is not duplicated with user
 * specified name, so use '\0';
 */
const DUMMY_COMPONENT_NAME_PREFIX = 'series\0';

const INTERNAL_COMPONENT_ID_PREFIX = '\0_ec_\0';

/**
 * If value is not array, then translate it to array.
 * @param  {*} value
 * @return {Array} [value] or value
 */
export function normalizeToArray<T>(value?: T | T[]): T[] {
    return value instanceof Array
        ? value
        : value == null
        ? []
        : [value];
}

/**
 * Sync default option between normal and emphasis like `position` and `show`
 * In case some one will write code like
 *     label: {
 *          show: false,
 *          position: 'outside',
 *          fontSize: 18
 *     },
 *     emphasis: {
 *          label: { show: true }
 *     }
 */
export function defaultEmphasis(
    opt: DisplayStateHostOption,
    key: string,
    subOpts: string[]
): void {
    // Caution: performance sensitive.
    if (opt) {
        opt[key] = opt[key] || {};
        opt.emphasis = opt.emphasis || {};
        opt.emphasis[key] = opt.emphasis[key] || {};

        // Default emphasis option from normal
        for (let i = 0, len = subOpts.length; i < len; i++) {
            const subOptName = subOpts[i];
            if (!opt.emphasis[key].hasOwnProperty(subOptName)
                && opt[key].hasOwnProperty(subOptName)
            ) {
                opt.emphasis[key][subOptName] = opt[key][subOptName];
            }
        }
    }
}

export const TEXT_STYLE_OPTIONS = [
    'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',
    'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth',
    'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline',
    'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY',
    'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY',
    'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding'
] as const;

// modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([
//     'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter',
//     'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',
//     // FIXME: deprecated, check and remove it.
//     'textStyle'
// ]);

/**
 * The method do not ensure performance.
 * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
 * This helper method retieves value from data.
 */
export function getDataItemValue(
    dataItem: OptionDataItem
): OptionDataValue | OptionDataValue[] {
    return (isObject(dataItem) && !isArray(dataItem) && !(dataItem instanceof Date))
        ? (dataItem as Dictionary<OptionDataValue>).value : dataItem;
}

/**
 * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
 * This helper method determine if dataItem has extra option besides value
 */
export function isDataItemOption(dataItem: OptionDataItem): boolean {
    return isObject(dataItem)
        && !(dataItem instanceof Array);
        // // markLine data can be array
        // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));
}

// Compatible with previous definition: id could be number (but not recommanded).
// number and string are trade the same when compare.
// number id will not be converted to string in option.
// number id will be converted to string in component instance id.
export interface MappingExistingItem {
    id?: OptionId;
    name?: string;
};
/**
 * The array `MappingResult<T>[]` exactly represents the content of the result
 * components array after merge.
 * The indices are the same as the `existings`.
 * Items will not be `null`/`undefined` even if the corresponding `existings` will be removed.
 */
type MappingResult<T> = MappingResultItem<T>[];
interface MappingResultItem<T extends MappingExistingItem = MappingExistingItem> {
    // Existing component instance.
    existing: T;
    // The mapped new component option.
    newOption: ComponentOption;
    // Mark that the new component has nothing to do with any of the old components.
    // So they won't share view. Also see `__requireNewView`.
    brandNew: boolean;
    // keyInfo for new component.
    // All of them will be assigned to a created component instance.
    keyInfo: {
        name: string,
        id: string,
        mainType: ComponentMainType,
        subType: ComponentSubType
    };
}

type MappingToExistsMode = 'normalMerge' | 'replaceMerge' | 'replaceAll';

/**
 * Mapping to existings for merge.
 *
 * Mode "normalMege":
 *     The mapping result (merge result) will keep the order of the existing
 *     component, rather than the order of new option. Because we should ensure
 *     some specified index reference (like xAxisIndex) keep work.
 *     And in most cases, "merge option" is used to update partial option but not
 *     be expected to change the order.
 *
 * Mode "replaceMege":
 *     (1) Only the id mapped components will be merged.
 *     (2) Other existing components (except internal compoonets) will be removed.
 *     (3) Other new options will be used to create new component.
 *     (4) The index of the existing compoents will not be modified.
 *     That means their might be "hole" after the removal.
 *     The new components are created first at those available index.
 *
 * Mode "replaceAll":
 *     This mode try to support that reproduce an echarts instance from another
 *     echarts instance (via `getOption`) in some simple cases.
 *     In this senario, the `result` index are exactly the consistent with the `newCmptOptions`,
 *     which ensures the compoennt index referring (like `xAxisIndex: ?`) corrent. That is,
 *     the "hole" in `newCmptOptions` will also be kept.
 *     On the contrary, other modes try best to eliminate holes.
 *     PENDING: This is an experimental mode yet.
 *
 * @return See the comment of <MappingResult>.
 */
export function mappingToExists<T extends MappingExistingItem>(
    existings: T[],
    newCmptOptions: ComponentOption[],
    mode: MappingToExistsMode
): MappingResult<T> {

    const isNormalMergeMode = mode === 'normalMerge';
    const isReplaceMergeMode = mode === 'replaceMerge';
    const isReplaceAllMode = mode === 'replaceAll';
    existings = existings || [];
    newCmptOptions = (newCmptOptions || []).slice();
    const existingIdIdxMap = createHashMap<number>();

    // Validate id and name on user input option.
    each(newCmptOptions, function (cmptOption, index) {
        if (!isObject<ComponentOption>(cmptOption)) {
            newCmptOptions[index] = null;
            return;
        }

        if (__DEV__) {
            // There is some legacy case that name is set as `false`.
            // But should work normally rather than throw error.
            if (cmptOption.id != null && !isValidIdOrName(cmptOption.id)) {
                warnInvalidateIdOrName(cmptOption.id);
            }
            if (cmptOption.name != null && !isValidIdOrName(cmptOption.name)) {
                warnInvalidateIdOrName(cmptOption.name);
            }
        }
    });

    const result = prepareResult(existings, existingIdIdxMap, mode);

    if (isNormalMergeMode || isReplaceMergeMode) {
        mappingById(result, existings, existingIdIdxMap, newCmptOptions);
    }

    if (isNormalMergeMode) {
        mappingByName(result, newCmptOptions);
    }

    if (isNormalMergeMode || isReplaceMergeMode) {
        mappingByIndex(result, newCmptOptions, isReplaceMergeMode);
    }
    else if (isReplaceAllMode) {
        mappingInReplaceAllMode(result, newCmptOptions);
    }

    makeIdAndName(result);

    // The array `result` MUST NOT contain elided items, otherwise the
    // forEach will ommit those items and result in incorrect result.
    return result;
}

function prepareResult<T extends MappingExistingItem>(
    existings: T[],
    existingIdIdxMap: HashMap<number>,
    mode: MappingToExistsMode
): MappingResultItem<T>[] {
    const result: MappingResultItem<T>[] = [];

    if (mode === 'replaceAll') {
        return result;
    }

    // Do not use native `map` to in case that the array `existings`
    // contains elided items, which will be ommited.
    for (let index = 0; index < existings.length; index++) {
        const existing = existings[index];
        // Because of replaceMerge, `existing` may be null/undefined.
        if (existing && existing.id != null) {
            existingIdIdxMap.set(existing.id, index);
        }
        // For non-internal-componnets:
        //     Mode "normalMerge": all existings kept.
        //     Mode "replaceMerge": all existing removed unless mapped by id.
        // For internal-components:
        //     go with "replaceMerge" approach in both mode.
        result.push({
            existing: (mode === 'replaceMerge' || isComponentIdInternal(existing))
                ? null
                : existing,
            newOption: null,
            keyInfo: null,
            brandNew: null
        });
    }
    return result;
}

function mappingById<T extends MappingExistingItem>(
    result: MappingResult<T>,
    existings: T[],
    existingIdIdxMap: HashMap<number>,
    newCmptOptions: ComponentOption[]
): void {
    // Mapping by id if specified.
    each(newCmptOptions, function (cmptOption, index) {
        if (!cmptOption || cmptOption.id == null) {
            return;
        }
        const optionId = makeComparableKey(cmptOption.id);
        const existingIdx = existingIdIdxMap.get(optionId);
        if (existingIdx != null) {
            const resultItem = result[existingIdx];
            assert(
                !resultItem.newOption,
                'Duplicated option on id "' + optionId + '".'
            );
            resultItem.newOption = cmptOption;
            // In both mode, if id matched, new option will be merged to
            // the existings rather than creating new component model.
            resultItem.existing = existings[existingIdx];
            newCmptOptions[index] = null;
        }
    });
}

function mappingByName<T extends MappingExistingItem>(
    result: MappingResult<T>,
    newCmptOptions: ComponentOption[]
): void {
    // Mapping by name if specified.
    each(newCmptOptions, function (cmptOption, index) {
        if (!cmptOption || cmptOption.name == null) {
            return;
        }
        for (let i = 0; i < result.length; i++) {
            const existing = result[i].existing;
            if (!result[i].newOption // Consider name: two map to one.
                // Can not match when both ids existing but different.
                && existing
                && (existing.id == null || cmptOption.id == null)
                && !isComponentIdInternal(cmptOption)
                && !isComponentIdInternal(existing)
                && keyExistAndEqual('name', existing, cmptOption)
            ) {
                result[i].newOption = cmptOption;
                newCmptOptions[index] = null;
                return;
            }
        }
    });
}

function mappingByIndex<T extends MappingExistingItem>(
    result: MappingResult<T>,
    newCmptOptions: ComponentOption[],
    brandNew: boolean
): void {
    each(newCmptOptions, function (cmptOption) {
        if (!cmptOption) {
            return;
        }

        // Find the first place that not mapped by id and not internal component (consider the "hole").
        let resultItem;
        let nextIdx = 0;
        while (
            // Be `!resultItem` only when `nextIdx >= result.length`.
            (resultItem = result[nextIdx])
            // (1) Existing models that already have id should be able to mapped to. Because
            // after mapping performed, model will always be assigned with an id if user not given.
            // After that all models have id.
            // (2) If new option has id, it can only set to a hole or append to the last. It should
            // not be merged to the existings with different id. Because id should not be overwritten.
            // (3) Name can be overwritten, because axis use name as 'show label text'.
            && (
                resultItem.newOption
                || isComponentIdInternal(resultItem.existing)
                || (
                    // In mode "replaceMerge", here no not-mapped-non-internal-existing.
                    resultItem.existing
                    && cmptOption.id != null
                    && !keyExistAndEqual('id', cmptOption, resultItem.existing)
                )
            )
        ) {
            nextIdx++;
        }

        if (resultItem) {
            resultItem.newOption = cmptOption;
            resultItem.brandNew = brandNew;
        }
        else {
            result.push({
                newOption: cmptOption,
                brandNew: brandNew,
                existing: null,
                keyInfo: null
            });
        }
        nextIdx++;
    });
}

function mappingInReplaceAllMode<T extends MappingExistingItem>(
    result: MappingResult<T>,
    newCmptOptions: ComponentOption[]
): void {
    each(newCmptOptions, function (cmptOption) {
        // The feature "reproduce" requires "hole" will also reproduced
        // in case that compoennt index referring are broken.
        result.push({
            newOption: cmptOption,
            brandNew: true,
            existing: null,
            keyInfo: null
        });
    });
}

/**
 * Make id and name for mapping result (result of mappingToExists)
 * into `keyInfo` field.
 */
function makeIdAndName(
    mapResult: MappingResult<MappingExistingItem>
): void {
    // We use this id to hash component models and view instances
    // in echarts. id can be specified by user, or auto generated.

    // The id generation rule ensures new view instance are able
    // to mapped to old instance when setOption are called in
    // no-merge mode. So we generate model id by name and plus
    // type in view id.

    // name can be duplicated among components, which is convenient
    // to specify multi components (like series) by one name.

    // Ensure that each id is distinct.
    const idMap = createHashMap();

    each(mapResult, function (item) {
        const existing = item.existing;
        existing && idMap.set(existing.id, item);
    });

    each(mapResult, function (item) {
        const opt = item.newOption;

        // Force ensure id not duplicated.
        assert(
            !opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item,
            'id duplicates: ' + (opt && opt.id)
        );

        opt && opt.id != null && idMap.set(opt.id, item);
        !item.keyInfo && (item.keyInfo = {} as MappingResultItem['keyInfo']);
    });

    // Make name and id.
    each(mapResult, function (item, index) {
        const existing = item.existing;
        const opt = item.newOption;
        const keyInfo = item.keyInfo;

        if (!isObject<ComponentOption>(opt)) {
            return;
        }

        // name can be overwitten. Consider case: axis.name = '20km'.
        // But id generated by name will not be changed, which affect
        // only in that case: setOption with 'not merge mode' and view
        // instance will be recreated, which can be accepted.
        keyInfo.name = opt.name != null
            ? makeComparableKey(opt.name)
            : existing
            ? existing.name
            // Avoid diffferent series has the same name,
            // because name may be used like in color pallet.
            : DUMMY_COMPONENT_NAME_PREFIX + index;

        if (existing) {
            keyInfo.id = makeComparableKey(existing.id);
        }
        else if (opt.id != null) {
            keyInfo.id = makeComparableKey(opt.id);
        }
        else {
            // Consider this situatoin:
            //  optionA: [{name: 'a'}, {name: 'a'}, {..}]
            //  optionB [{..}, {name: 'a'}, {name: 'a'}]
            // Series with the same name between optionA and optionB
            // should be mapped.
            let idNum = 0;
            do {
                keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++;
            }
            while (idMap.get(keyInfo.id));
        }

        idMap.set(keyInfo.id, item);
    });
}

function keyExistAndEqual(
    attr: 'id' | 'name',
    obj1: { id?: OptionId, name?: OptionName },
    obj2: { id?: OptionId, name?: OptionName }
): boolean {
    const key1 = convertOptionIdName(obj1[attr], null);
    const key2 = convertOptionIdName(obj2[attr], null);
    // See `MappingExistingItem`. `id` and `name` trade string equals to number.
    return key1 != null && key2 != null && key1 === key2;
}

/**
 * @return return null if not exist.
 */
function makeComparableKey(val: unknown): string {
    if (__DEV__) {
        if (val == null) {
            throw new Error();
        }
    }
    return convertOptionIdName(val, '');
}

export function convertOptionIdName(idOrName: unknown, defaultValue: string): string {
    if (idOrName == null) {
        return defaultValue;
    }
    const type = typeof idOrName;
    return type === 'string'
        ? idOrName as string
        : (type === 'number' || isStringSafe(idOrName))
        ? idOrName + ''
        : defaultValue;
}

function warnInvalidateIdOrName(idOrName: unknown) {
    if (__DEV__) {
        warn('`' + idOrName + '` is invalid id or name. Must be a string or number.');
    }
}

function isValidIdOrName(idOrName: unknown): boolean {
    return isStringSafe(idOrName) || isNumeric(idOrName);
}

export function isNameSpecified(componentModel: ComponentModel): boolean {
    const name = componentModel.name;
    // Is specified when `indexOf` get -1 or > 0.
    return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX));
}

/**
 * @public
 * @param {Object} cmptOption
 * @return {boolean}
 */
export function isComponentIdInternal(cmptOption: { id?: MappingExistingItem['id'] }): boolean {
    return cmptOption
        && cmptOption.id != null
        && makeComparableKey(cmptOption.id).indexOf(INTERNAL_COMPONENT_ID_PREFIX) === 0;
}

export function makeInternalComponentId(idSuffix: string) {
    return INTERNAL_COMPONENT_ID_PREFIX + idSuffix;
}

export function setComponentTypeToKeyInfo(
    mappingResult: MappingResult<MappingExistingItem & { subType?: ComponentSubType }>,
    mainType: ComponentMainType,
    componentModelCtor: ComponentModelConstructor
): void {
    // Set mainType and complete subType.
    each(mappingResult, function (item) {
        const newOption = item.newOption;
        if (isObject(newOption)) {
            item.keyInfo.mainType = mainType;
            item.keyInfo.subType = determineSubType(mainType, newOption, item.existing, componentModelCtor);
        }
    });
}

function determineSubType(
    mainType: ComponentMainType,
    newCmptOption: ComponentOption,
    existComponent: { subType?: ComponentSubType },
    componentModelCtor: ComponentModelConstructor
): ComponentSubType {
    const subType = newCmptOption.type
        ? newCmptOption.type
        : existComponent
        ? existComponent.subType
        // Use determineSubType only when there is no existComponent.
        : (componentModelCtor as ComponentModelConstructor).determineSubType(mainType, newCmptOption);

    // tooltip, markline, markpoint may always has no subType
    return subType;
}


type BatchItem = {
    seriesId: OptionId,
    dataIndex: number | number[]
};
/**
 * A helper for removing duplicate items between batchA and batchB,
 * and in themselves, and categorize by series.
 *
 * @param batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]
 * @param batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]
 * @return result: [resultBatchA, resultBatchB]
 */
export function compressBatches(
    batchA: BatchItem[],
    batchB: BatchItem[]
): [BatchItem[], BatchItem[]] {

    type InnerMap = {
        [seriesId: string]: {
            [dataIndex: string]: 1
        }
    };
    const mapA = {} as InnerMap;
    const mapB = {} as InnerMap;

    makeMap(batchA || [], mapA);
    makeMap(batchB || [], mapB, mapA);

    return [mapToArray(mapA), mapToArray(mapB)];

    function makeMap(sourceBatch: BatchItem[], map: InnerMap, otherMap?: InnerMap): void {
        for (let i = 0, len = sourceBatch.length; i < len; i++) {
            const seriesId = convertOptionIdName(sourceBatch[i].seriesId, null);
            if (seriesId == null) {
                return;
            }
            const dataIndices = normalizeToArray(sourceBatch[i].dataIndex);
            const otherDataIndices = otherMap && otherMap[seriesId];

            for (let j = 0, lenj = dataIndices.length; j < lenj; j++) {
                const dataIndex = dataIndices[j];

                if (otherDataIndices && otherDataIndices[dataIndex]) {
                    otherDataIndices[dataIndex] = null;
                }
                else {
                    (map[seriesId] || (map[seriesId] = {}))[dataIndex] = 1;
                }
            }
        }
    }

    function mapToArray(map: Dictionary<any>, isData?: boolean): any[] {
        const result = [];
        for (const i in map) {
            if (map.hasOwnProperty(i) && map[i] != null) {
                if (isData) {
                    result.push(+i);
                }
                else {
                    const dataIndices = mapToArray(map[i], true);
                    dataIndices.length && result.push({seriesId: i, dataIndex: dataIndices});
                }
            }
        }
        return result;
    }
}

/**
 * @param payload Contains dataIndex (means rawIndex) / dataIndexInside / name
 *                         each of which can be Array or primary type.
 * @return dataIndex If not found, return undefined/null.
 */
export function queryDataIndex(data: List, payload: Payload & {
    dataIndexInside?: number | number[]
    dataIndex?: number | number[]
    name?: string | string[]
}): number | number[] {
    if (payload.dataIndexInside != null) {
        return payload.dataIndexInside;
    }
    else if (payload.dataIndex != null) {
        return isArray(payload.dataIndex)
            ? map(payload.dataIndex, function (value) {
                return data.indexOfRawIndex(value);
            })
            : data.indexOfRawIndex(payload.dataIndex);
    }
    else if (payload.name != null) {
        return isArray(payload.name)
            ? map(payload.name, function (value) {
                return data.indexOfName(value);
            })
            : data.indexOfName(payload.name);
    }
}

/**
 * Enable property storage to any host object.
 * Notice: Serialization is not supported.
 *
 * For example:
 * let inner = zrUitl.makeInner();
 *
 * function some1(hostObj) {
 *      inner(hostObj).someProperty = 1212;
 *      ...
 * }
 * function some2() {
 *      let fields = inner(this);
 *      fields.someProperty1 = 1212;
 *      fields.someProperty2 = 'xx';
 *      ...
 * }
 *
 * @return {Function}
 */
export function makeInner<T, Host extends object>() {
    const key = '__ec_inner_' + innerUniqueIndex++;
    return function (hostObj: Host): T {
        return (hostObj as any)[key] || ((hostObj as any)[key] = {});
    };
}
let innerUniqueIndex = getRandomIdBase();

/**
 * If string, e.g., 'geo', means {geoIndex: 0}.
 * If Object, could contain some of these properties below:
 * {
 *     seriesIndex, seriesId, seriesName,
 *     geoIndex, geoId, geoName,
 *     bmapIndex, bmapId, bmapName,
 *     xAxisIndex, xAxisId, xAxisName,
 *     yAxisIndex, yAxisId, yAxisName,
 *     gridIndex, gridId, gridName,
 *     ... (can be extended)
 * }
 * Each properties can be number|string|Array.<number>|Array.<string>
 * For example, a finder could be
 * {
 *     seriesIndex: 3,
 *     geoId: ['aa', 'cc'],
 *     gridName: ['xx', 'rr']
 * }
 * xxxIndex can be set as 'all' (means all xxx) or 'none' (means not specify)
 * If nothing or null/undefined specified, return nothing.
 * If both `abcIndex`, `abcId`, `abcName` specified, only one work.
 * The priority is: index > id > name, the same with `ecModel.queryComponents`.
 */
export type ModelFinderIndexQuery = number | number[] | 'all' | 'none' | false;
export type ModelFinderIdQuery = OptionId | OptionId[];
export type ModelFinderNameQuery = OptionId | OptionId[];
// If string, like 'series', means { seriesIndex: 0 }.
export type ModelFinder = string | ModelFinderObject;
export type ModelFinderObject = {
    seriesIndex?: ModelFinderIndexQuery, seriesId?: ModelFinderIdQuery, seriesName?: ModelFinderNameQuery
    geoIndex?: ModelFinderIndexQuery, geoId?: ModelFinderIdQuery, geoName?: ModelFinderNameQuery
    bmapIndex?: ModelFinderIndexQuery, bmapId?: ModelFinderIdQuery, bmapName?: ModelFinderNameQuery
    xAxisIndex?: ModelFinderIndexQuery, xAxisId?: ModelFinderIdQuery, xAxisName?: ModelFinderNameQuery
    yAxisIndex?: ModelFinderIndexQuery, yAxisId?: ModelFinderIdQuery, yAxisName?: ModelFinderNameQuery
    gridIndex?: ModelFinderIndexQuery, gridId?: ModelFinderIdQuery, gridName?: ModelFinderNameQuery
    dataIndex?: number, dataIndexInside?: number
    // ... (can be extended)
};
/**
 * {
 *     seriesModels: [seriesModel1, seriesModel2],
 *     seriesModel: seriesModel1, // The first model
 *     geoModels: [geoModel1, geoModel2],
 *     geoModel: geoModel1, // The first model
 *     ...
 * }
 */
export type ParsedModelFinder = {
    // other components
    [key: string]: ComponentModel | ComponentModel[] | undefined;
};

export type ParsedModelFinderKnown = ParsedModelFinder & {
    seriesModels?: SeriesModel[];
    seriesModel?: SeriesModel;
    xAxisModels?: CartesianAxisModel[];
    xAxisModel?: CartesianAxisModel;
    yAxisModels?: CartesianAxisModel[];
    yAxisModel?: CartesianAxisModel;
    gridModels?: GridModel[];
    gridModel?: GridModel;
    dataIndex?: number;
    dataIndexInside?: number;
};

/**
 * The same behavior as `component.getReferringComponents`.
 */
export function parseFinder(
    ecModel: GlobalModel,
    finderInput: ModelFinder,
    opt?: {
        // If no main type specified, use this main type.
        defaultMainType?: ComponentMainType;
        // If pervided, types out of this list will be ignored.
        includeMainTypes?: ComponentMainType[];
        enableAll?: boolean;
        enableNone?: boolean;
    }
): ParsedModelFinder {
    const { mainTypeSpecified, queryOptionMap, others } = preParseFinder(finderInput, opt);
    const result = others as ParsedModelFinderKnown;

    const defaultMainType = opt ? opt.defaultMainType : null;
    if (!mainTypeSpecified && defaultMainType) {
        queryOptionMap.set(defaultMainType, {});
    }

    queryOptionMap.each(function (queryOption, mainType) {
        const queryResult = queryReferringComponents(
            ecModel,
            mainType,
            queryOption,
            {
                useDefault: defaultMainType === mainType,
                enableAll: (opt && opt.enableAll != null) ? opt.enableAll : true,
                enableNone: (opt && opt.enableNone != null) ? opt.enableNone : true
            }
        );
        result[mainType + 'Models'] = queryResult.models;
        result[mainType + 'Model'] = queryResult.models[0];
    });

    return result;
}

export function preParseFinder(
    finderInput: ModelFinder,
    opt?: {
        // If pervided, types out of this list will be ignored.
        includeMainTypes?: ComponentMainType[];
    }
): {
    mainTypeSpecified: boolean;
    queryOptionMap: HashMap<QueryReferringUserOption, ComponentMainType>;
    others: Partial<Pick<ParsedModelFinderKnown, 'dataIndex' | 'dataIndexInside'>>
} {
    let finder: ModelFinderObject;
    if (isString(finderInput)) {
        const obj = {};
        (obj as any)[finderInput + 'Index'] = 0;
        finder = obj;
    }
    else {
        finder = finderInput;
    }

    const queryOptionMap = createHashMap<QueryReferringUserOption, ComponentMainType>();
    const others = {} as Partial<Pick<ParsedModelFinderKnown, 'dataIndex' | 'dataIndexInside'>>;
    let mainTypeSpecified = false;

    each(finder, function (value, key) {
        // Exclude 'dataIndex' and other illgal keys.
        if (key === 'dataIndex' || key === 'dataIndexInside') {
            others[key] = value as number;
            return;
        }

        const parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || [];
        const mainType = parsedKey[1];
        const queryType = (parsedKey[2] || '').toLowerCase() as keyof QueryReferringUserOption;

        if (
            !mainType
            || !queryType
            || (opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0)
        ) {
            return;
        }

        mainTypeSpecified = mainTypeSpecified || !!mainType;

        const queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {});
        queryOption[queryType] = value as any;
    });

    return { mainTypeSpecified, queryOptionMap, others };
}


export type QueryReferringUserOption = {
    index?: ModelFinderIndexQuery,
    id?: ModelFinderIdQuery,
    name?: ModelFinderNameQuery,
};

export const SINGLE_REFERRING: QueryReferringOpt = { useDefault: true, enableAll: false, enableNone: false };
export const MULTIPLE_REFERRING: QueryReferringOpt = { useDefault: false, enableAll: true, enableNone: true };

export type QueryReferringOpt = {
    // Whether to use the first componet as the default if none of index/id/name are specified.
    useDefault?: boolean;
    // Whether to enable `'all'` on index option.
    enableAll?: boolean;
    // Whether to enable `'none'`/`false` on index option.
    enableNone?: boolean;
};

export function queryReferringComponents(
    ecModel: GlobalModel,
    mainType: ComponentMainType,
    userOption: QueryReferringUserOption,
    opt?: QueryReferringOpt
): {
    // Always be array rather than null/undefined, which is convenient to use.
    models: ComponentModel[];
    // Whether there is indexOption/id/name specified
    specified: boolean;
} {
    opt = opt || SINGLE_REFERRING as QueryReferringOpt;
    let indexOption = userOption.index;
    let idOption = userOption.id;
    let nameOption = userOption.name;

    const result = {
        models: null as ComponentModel[],
        specified: indexOption != null || idOption != null || nameOption != null
    };

    if (!result.specified) {
        // Use the first as default if `useDefault`.
        let firstCmpt;
        result.models = (
            opt.useDefault && (firstCmpt = ecModel.getComponent(mainType))
        ) ? [firstCmpt] : [];
        return result;
    }

    if (indexOption === 'none' || indexOption === false) {
        assert(opt.enableNone, '`"none"` or `false` is not a valid value on index option.');
        result.models = [];
        return result;
    }

    // `queryComponents` will return all components if
    // both all of index/id/name are null/undefined.
    if (indexOption === 'all') {
        assert(opt.enableAll, '`"all"` is not a valid value on index option.');
        indexOption = idOption = nameOption = null;
    }
    result.models = ecModel.queryComponents({
        mainType: mainType,
        index: indexOption as number | number[],
        id: idOption,
        name: nameOption
    });
    return result;
}

export function setAttribute(dom: HTMLElement, key: string, value: any) {
    dom.setAttribute
        ? dom.setAttribute(key, value)
        : ((dom as any)[key] = value);
}

export function getAttribute(dom: HTMLElement, key: string): any {
    return dom.getAttribute
        ? dom.getAttribute(key)
        : (dom as any)[key];
}

export function getTooltipRenderMode(renderModeOption: TooltipRenderMode | 'auto'): TooltipRenderMode {
    if (renderModeOption === 'auto') {
        // Using html when `document` exists, use richText otherwise
        return env.domSupported ? 'html' : 'richText';
    }
    else {
        return renderModeOption || 'html';
    }
}

/**
 * Group a list by key.
 */
export function groupData<T, R extends string | number>(
    array: T[],
    getKey: (item: T) => R // return key
): {
    keys: R[],
    buckets: HashMap<T[], R> // hasmap key: the key returned by `getKey`.
} {
    const buckets = createHashMap<T[], R>();
    const keys: R[] = [];

    each(array, function (item) {
        const key = getKey(item);
        (buckets.get(key)
            || (keys.push(key), buckets.set(key, []))
        ).push(item);
    });

    return {
        keys: keys,
        buckets: buckets
    };
}


/**
 * Interpolate raw values of a series with percent
 *
 * @param data         data
 * @param labelModel   label model of the text element
 * @param sourceValue  start value. May be null/undefined when init.
 * @param targetValue  end value
 * @param percent      0~1 percentage; 0 uses start value while 1 uses end value
 * @return             interpolated values
 *                     If `sourceValue` and `targetValue` are `number`, return `number`.
 *                     If `sourceValue` and `targetValue` are `string`, return `string`.
 *                     If `sourceValue` and `targetValue` are `(string | number)[]`, return `(string | number)[]`.
 *                     Other cases do not supported.
 */
export function interpolateRawValues(
    data: List,
    precision: number | 'auto',
    sourceValue: InterpolatableValue,
    targetValue: InterpolatableValue,
    percent: number
): InterpolatableValue {
    const isAutoPrecision = precision == null || precision === 'auto';

    if (targetValue == null) {
        return targetValue;
    }

    if (typeof targetValue === 'number') {
        const value = interpolateNumber(
            sourceValue as number || 0,
            targetValue as number,
            percent
        );
        return round(
            value,
            isAutoPrecision ? Math.max(
                getPrecision(sourceValue as number || 0),
                getPrecision(targetValue as number)
            )
            : precision as number
        );
    }
    else if (typeof targetValue === 'string') {
        return percent < 1 ? sourceValue : targetValue;
    }
    else {
        const interpolated = [];
        const leftArr = sourceValue as (string | number)[];
        const rightArr = targetValue as (string | number[]);
        const length = Math.max(leftArr ? leftArr.length : 0, rightArr.length);
        for (let i = 0; i < length; ++i) {
            const info = data.getDimensionInfo(i);
            // Don't interpolate ordinal dims
            if (info.type === 'ordinal') {
                // In init, there is no `sourceValue`, but should better not to get undefined result.
                interpolated[i] = (percent < 1 && leftArr ? leftArr : rightArr)[i] as number;
            }
            else {
                const leftVal = leftArr && leftArr[i] ? leftArr[i] as number : 0;
                const rightVal = rightArr[i] as number;
                const value = interpolateNumber(leftVal, rightVal, percent);
                interpolated[i] = round(
                    value,
                    isAutoPrecision ? Math.max(
                        getPrecision(leftVal),
                        getPrecision(rightVal)
                    )
                    : precision as number
                );
            }
        }
        return interpolated;
    }
}