/*
* 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 { assert, clone, createHashMap, isFunction, keys, map, reduce } from 'zrender/src/core/util';
import {
    DimensionIndex,
    DimensionName,
    OptionDataItem,
    ParsedValue,
    ParsedValueNumeric
} from '../util/types';
import { DataProvider } from './helper/dataProvider';
import { parseDataValue } from './helper/dataValueHelper';
import OrdinalMeta from './OrdinalMeta';
import { shouldRetrieveDataByName, Source } from './Source';

const UNDEFINED = 'undefined';
/* global Float64Array, Int32Array, Uint32Array, Uint16Array */

// Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is
// different from the Ctor of typed array.
export const CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array;
export const CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array;
export const CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array;
export const CtorFloat64Array = typeof Float64Array === UNDEFINED ? Array : Float64Array;
/**
 * Multi dimensional data store
 */
const dataCtors = {
    'float': CtorFloat64Array,
    'int': CtorInt32Array,
    // Ordinal data type can be string or int
    'ordinal': Array,
    'number': Array,
    'time': CtorFloat64Array
} as const;

export type DataStoreDimensionType = keyof typeof dataCtors;

type DataTypedArray = Uint32Array | Int32Array | Uint16Array | Float64Array;
type DataTypedArrayConstructor = typeof Uint32Array | typeof Int32Array | typeof Uint16Array | typeof Float64Array;
type DataArrayLikeConstructor = typeof Array | DataTypedArrayConstructor;


type DataValueChunk = ArrayLike<ParsedValue>;

// If Ctx not specified, use List as Ctx
type EachCb0 = (idx: number) => void;
type EachCb1 = (x: ParsedValue, idx: number) => void;
type EachCb2 = (x: ParsedValue, y: ParsedValue, idx: number) => void;
type EachCb = (...args: any) => void;
type FilterCb0 = (idx: number) => boolean;
type FilterCb1 = (x: ParsedValue, idx: number) => boolean;
type FilterCb = (...args: any) => boolean;
// type MapArrayCb = (...args: any) => any;
type MapCb = (...args: any) => ParsedValue | ParsedValue[];

export type DimValueGetter = (
    this: DataStore,
    dataItem: any,
    property: string,
    dataIndex: number,
    dimIndex: DimensionIndex
) => ParsedValue;

export interface DataStoreDimensionDefine {
    /**
     * Default to be float.
     */
    type?: DataStoreDimensionType;

    /**
     * Only used in SOURCE_FORMAT_OBJECT_ROWS and SOURCE_FORMAT_KEYED_COLUMNS to retrieve value
     * by "object property".
     * For example, in `[{bb: 124, aa: 543}, ...]`, "aa" and "bb" is "object property".
     *
     * Deliberately name it as "property" rather than "name" to prevent it from been used in
     * SOURCE_FORMAT_ARRAY_ROWS, because if it comes from series, it probably
     * can not be shared by different series.
     */
    property?: string;

    /**
     * When using category axis.
     * Category strings will be collected and stored in ordinalMeta.categories.
     * And store will store the index of categories.
     */
    ordinalMeta?: OrdinalMeta,

    /**
     * Offset for ordinal parsing and collect
     */
    ordinalOffset?: number
}

let defaultDimValueGetters: {[sourceFormat: string]: DimValueGetter};

function getIndicesCtor(rawCount: number): DataArrayLikeConstructor {
    // The possible max value in this._indicies is always this._rawCount despite of filtering.
    return rawCount > 65535 ? CtorUint32Array : CtorUint16Array;
};
function getInitialExtent(): [number, number] {
    return [Infinity, -Infinity];
};
function cloneChunk(originalChunk: DataValueChunk): DataValueChunk {
    const Ctor = originalChunk.constructor;
    // Only shallow clone is enough when Array.
    return Ctor === Array
        ? (originalChunk as Array<ParsedValue>).slice()
        : new (Ctor as DataTypedArrayConstructor)(originalChunk as DataTypedArray);
}

function prepareStore(
    store: DataValueChunk[],
    dimIdx: number,
    dimType: DataStoreDimensionType,
    end: number,
    append?: boolean
): void {
    const DataCtor = dataCtors[dimType || 'float'];

    if (append) {
        const oldStore = store[dimIdx];
        const oldLen = oldStore && oldStore.length;
        if (!(oldLen === end)) {
            const newStore = new DataCtor(end);
            // The cost of the copy is probably inconsiderable
            // within the initial chunkSize.
            for (let j = 0; j < oldLen; j++) {
                newStore[j] = oldStore[j];
            }
            store[dimIdx] = newStore;
        }
    }
    else {
        store[dimIdx] = new DataCtor(end);
    }
};

/**
 * Basically, DataStore API keep immutable.
 */
class DataStore {
    private _chunks: DataValueChunk[] = [];

    private _provider: DataProvider;

    // It will not be calculated util needed.
    private _rawExtent: [number, number][] = [];

    private _extent: [number, number][] = [];

    // Indices stores the indices of data subset after filtered.
    // This data subset will be used in chart.
    private _indices: ArrayLike<any>;

    private _count: number = 0;
    private _rawCount: number = 0;

    private _dimensions: DataStoreDimensionDefine[];
    private _dimValueGetter: DimValueGetter;

    private _calcDimNameToIdx = createHashMap<DimensionIndex, DimensionName>();

    defaultDimValueGetter: DimValueGetter;

    /**
     * Initialize from data
     */
    initData(
        provider: DataProvider,
        inputDimensions: DataStoreDimensionDefine[],
        dimValueGetter?: DimValueGetter
    ): void {
        if (__DEV__) {
            assert(
                isFunction(provider.getItem) && isFunction(provider.count),
                'Invalid data provider.'
            );
        }

        this._provider = provider;

        // Clear
        this._chunks = [];
        this._indices = null;
        this.getRawIndex = this._getRawIdxIdentity;

        const source = provider.getSource();
        const defaultGetter = this.defaultDimValueGetter =
             defaultDimValueGetters[source.sourceFormat];
        // Default dim value getter
        this._dimValueGetter = dimValueGetter || defaultGetter;

        // Reset raw extent.
        this._rawExtent = [];
        const willRetrieveDataByName = shouldRetrieveDataByName(source);
        this._dimensions = map(inputDimensions, dim => {
            if (__DEV__) {
                if (willRetrieveDataByName) {
                    assert(dim.property != null);
                }
            }
            return {
                // Only pick these two props. Not leak other properties like orderMeta.
                type: dim.type,
                property: dim.property
            };
        });

        this._initDataFromProvider(0, provider.count());
    }

    getProvider(): DataProvider {
        return this._provider;
    }

    /**
     * Caution: even when a `source` instance owned by a series, the created data store
     * may still be shared by different sereis (the source hash does not use all `source`
     * props, see `sourceManager`). In this case, the `source` props that are not used in
     * hash (like `source.dimensionDefine`) probably only belongs to a certain series and
     * thus should not be fetch here.
     */
    getSource(): Source {
        return this._provider.getSource();
    }

    /**
     * @caution Only used in dataStack.
     */
    ensureCalculationDimension(dimName: DimensionName, type: DataStoreDimensionType): DimensionIndex {
        const calcDimNameToIdx = this._calcDimNameToIdx;
        const dimensions = this._dimensions;

        let calcDimIdx = calcDimNameToIdx.get(dimName);
        if (calcDimIdx != null) {
            if (dimensions[calcDimIdx].type === type) {
                return calcDimIdx;
            }
        }
        else {
            calcDimIdx = dimensions.length;
        }

        dimensions[calcDimIdx] = { type: type };
        calcDimNameToIdx.set(dimName, calcDimIdx);

        this._chunks[calcDimIdx] = new dataCtors[type || 'float'](this._rawCount);
        this._rawExtent[calcDimIdx] = getInitialExtent();

        return calcDimIdx;
    }

    collectOrdinalMeta(
        dimIdx: number,
        ordinalMeta: OrdinalMeta
    ): void {
        const chunk = this._chunks[dimIdx];
        const dim = this._dimensions[dimIdx];
        const rawExtents = this._rawExtent;

        const offset = dim.ordinalOffset || 0;
        const len = chunk.length;

        if (offset === 0) {
            // We need to reset the rawExtent if collect is from start.
            // Because this dimension may be guessed as number and calcuating a wrong extent.
            rawExtents[dimIdx] = getInitialExtent();
        }

        const dimRawExtent = rawExtents[dimIdx];

        // Parse from previous data offset. len may be changed after appendData
        for (let i = offset; i < len; i++) {
            const val = (chunk as any)[i] = ordinalMeta.parseAndCollect(chunk[i]);
            if (!isNaN(val)) {
                dimRawExtent[0] = Math.min(val, dimRawExtent[0]);
                dimRawExtent[1] = Math.max(val, dimRawExtent[1]);
            }
        }

        dim.ordinalMeta = ordinalMeta;
        dim.ordinalOffset = len;
        dim.type = 'ordinal';   // Force to be ordinal
    }

    getOrdinalMeta(dimIdx: number): OrdinalMeta {
        const dimInfo = this._dimensions[dimIdx];
        const ordinalMeta = dimInfo.ordinalMeta;
        return ordinalMeta;
    }

    getDimensionProperty(dimIndex: DimensionIndex): DataStoreDimensionDefine['property'] {
        const item = this._dimensions[dimIndex];
        return item && item.property;
    }

    /**
     * Caution: Can be only called on raw data (before `this._indices` created).
     */
    appendData(data: ArrayLike<any>): number[] {
        if (__DEV__) {
            assert(!this._indices, 'appendData can only be called on raw data.');
        }

        const provider = this._provider;
        const start = this.count();
        provider.appendData(data);
        let end = provider.count();
        if (!provider.persistent) {
            end += start;
        }

        if (start < end) {
            this._initDataFromProvider(start, end, true);
        }

        return [start, end];
    }

    appendValues(values: any[][], minFillLen?: number): { start: number; end: number } {
        const chunks = this._chunks;
        const dimensions = this._dimensions;
        const dimLen = dimensions.length;
        const rawExtent = this._rawExtent;

        const start = this.count();
        const end = start + Math.max(values.length, minFillLen || 0);

        for (let i = 0; i < dimLen; i++) {
            const dim = dimensions[i];
            prepareStore(chunks, i, dim.type, end, true);
        }

        const emptyDataItem: number[] = [];
        for (let idx = start; idx < end; idx++) {
            const sourceIdx = idx - start;
            // Store the data by dimensions
            for (let dimIdx = 0; dimIdx < dimLen; dimIdx++) {
                const dim = dimensions[dimIdx];
                const val = defaultDimValueGetters.arrayRows.call(
                    this, values[sourceIdx] || emptyDataItem, dim.property, sourceIdx, dimIdx
                ) as ParsedValueNumeric;
                (chunks[dimIdx] as any)[idx] = val;

                const dimRawExtent = rawExtent[dimIdx];
                val < dimRawExtent[0] && (dimRawExtent[0] = val);
                val > dimRawExtent[1] && (dimRawExtent[1] = val);
            }
        }

        this._rawCount = this._count = end;

        return {start, end};
    }

    private _initDataFromProvider(
        start: number,
        end: number,
        append?: boolean
    ): void {
        const provider = this._provider;
        const chunks = this._chunks;
        const dimensions = this._dimensions;
        const dimLen = dimensions.length;
        const rawExtent = this._rawExtent;
        const dimNames = map(dimensions, dim => dim.property);

        for (let i = 0; i < dimLen; i++) {
            const dim = dimensions[i];
            if (!rawExtent[i]) {
                rawExtent[i] = getInitialExtent();
            }
            prepareStore(chunks, i, dim.type, end, append);
        }

        if (provider.fillStorage) {
            provider.fillStorage(start, end, chunks, rawExtent);
        }
        else {
            let dataItem = [] as OptionDataItem;
            for (let idx = start; idx < end; idx++) {
                // NOTICE: Try not to write things into dataItem
                dataItem = provider.getItem(idx, dataItem);
                // Each data item is value
                // [1, 2]
                // 2
                // Bar chart, line chart which uses category axis
                // only gives the 'y' value. 'x' value is the indices of category
                // Use a tempValue to normalize the value to be a (x, y) value

                // Store the data by dimensions
                for (let dimIdx = 0; dimIdx < dimLen; dimIdx++) {
                    const dimStorage = chunks[dimIdx];
                    // PENDING NULL is empty or zero
                    const val = this._dimValueGetter(
                        dataItem, dimNames[dimIdx], idx, dimIdx
                    ) as ParsedValueNumeric;
                    (dimStorage as ParsedValue[])[idx] = val;

                    const dimRawExtent = rawExtent[dimIdx];
                    val < dimRawExtent[0] && (dimRawExtent[0] = val);
                    val > dimRawExtent[1] && (dimRawExtent[1] = val);
                }
            }
        }

        if (!provider.persistent && provider.clean) {
            // Clean unused data if data source is typed array.
            provider.clean();
        }

        this._rawCount = this._count = end;
        // Reset data extent
        this._extent = [];
    }

    count(): number {
        return this._count;
    }

    /**
     * Get value. Return NaN if idx is out of range.
     */
    get(dim: DimensionIndex, idx: number): ParsedValue {
        if (!(idx >= 0 && idx < this._count)) {
            return NaN;
        }
        const dimStore = this._chunks[dim];
        return dimStore ? dimStore[this.getRawIndex(idx)] : NaN;
    }

    getValues(idx: number): ParsedValue[];
    getValues(dimensions: readonly DimensionIndex[], idx?: number): ParsedValue[];
    getValues(dimensions: readonly DimensionIndex[] | number, idx?: number): ParsedValue[] {
        const values = [];
        let dimArr: DimensionIndex[] = [];
        if (idx == null) {
            idx = dimensions as number;
            // TODO get all from store?
            dimensions = [];
            // All dimensions
            for (let i = 0; i < this._dimensions.length; i++) {
                dimArr.push(i);
            }
        }
        else {
            dimArr = dimensions as DimensionIndex[];
        }

        for (let i = 0, len = dimArr.length; i < len; i++) {
            values.push(this.get(dimArr[i], idx));
        }

        return values;
    }

    /**
     * @param dim concrete dim
     */
    getByRawIndex(dim: DimensionIndex, rawIdx: number): ParsedValue {
        if (!(rawIdx >= 0 && rawIdx < this._rawCount)) {
            return NaN;
        }
        const dimStore = this._chunks[dim];
        return dimStore ? dimStore[rawIdx] : NaN;
    }

    /**
     * Get sum of data in one dimension
     */
    getSum(dim: DimensionIndex): number {
        const dimData = this._chunks[dim];
        let sum = 0;
        if (dimData) {
            for (let i = 0, len = this.count(); i < len; i++) {
                const value = this.get(dim, i) as number;
                if (!isNaN(value)) {
                    sum += value;
                }
            }
        }
        return sum;
    }

    /**
     * Get median of data in one dimension
     */
    getMedian(dim: DimensionIndex): number {
        const dimDataArray: ParsedValue[] = [];
        // map all data of one dimension
        this.each([dim], function (val) {
            if (!isNaN(val as number)) {
                dimDataArray.push(val);
            }
        });

        // TODO
        // Use quick select?
        const sortedDimDataArray = dimDataArray.sort(function (a: number, b: number) {
            return a - b;
        }) as number[];
        const len = this.count();
        // calculate median
        return len === 0
            ? 0
            : len % 2 === 1
            ? sortedDimDataArray[(len - 1) / 2]
            : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2;
    }

    /**
     * Retrieve the index with given raw data index.
     */
    indexOfRawIndex(rawIndex: number): number {
        if (rawIndex >= this._rawCount || rawIndex < 0) {
            return -1;
        }

        if (!this._indices) {
            return rawIndex;
        }

        // Indices are ascending
        const indices = this._indices;

        // If rawIndex === dataIndex
        const rawDataIndex = indices[rawIndex];
        if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) {
            return rawIndex;
        }

        let left = 0;
        let right = this._count - 1;
        while (left <= right) {
            const mid = (left + right) / 2 | 0;
            if (indices[mid] < rawIndex) {
                left = mid + 1;
            }
            else if (indices[mid] > rawIndex) {
                right = mid - 1;
            }
            else {
                return mid;
            }
        }
        return -1;
    }


    /**
     * Retrieve the index of nearest value.
     * @param dim
     * @param value
     * @param [maxDistance=Infinity]
     * @return If and only if multiple indices have
     *         the same value, they are put to the result.
     */
    indicesOfNearest(
        dim: DimensionIndex, value: number, maxDistance?: number
    ): number[] {
        const chunks = this._chunks;
        const dimData = chunks[dim];
        const nearestIndices: number[] = [];

        if (!dimData) {
            return nearestIndices;
        }

        if (maxDistance == null) {
            maxDistance = Infinity;
        }

        let minDist = Infinity;
        let minDiff = -1;
        let nearestIndicesLen = 0;

        // Check the test case of `test/ut/spec/data/SeriesData.js`.
        for (let i = 0, len = this.count(); i < len; i++) {
            const dataIndex = this.getRawIndex(i);
            const diff = value - (dimData[dataIndex] as number);
            const dist = Math.abs(diff);
            if (dist <= maxDistance) {
                // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,
                // we'd better not push both of them to `nearestIndices`, otherwise it is easy to
                // get more than one item in `nearestIndices` (more specifically, in `tooltip`).
                // So we chose the one that `diff >= 0` in this csae.
                // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them
                // should be push to `nearestIndices`.
                if (dist < minDist
                    || (dist === minDist && diff >= 0 && minDiff < 0)
                ) {
                    minDist = dist;
                    minDiff = diff;
                    nearestIndicesLen = 0;
                }
                if (diff === minDiff) {
                    nearestIndices[nearestIndicesLen++] = i;
                }
            }
        }
        nearestIndices.length = nearestIndicesLen;

        return nearestIndices;
    }

    getIndices(): ArrayLike<number> {
        let newIndices;

        const indices = this._indices;
        if (indices) {
            const Ctor = indices.constructor as DataArrayLikeConstructor;
            const thisCount = this._count;
            // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.
            if (Ctor === Array) {
                newIndices = new Ctor(thisCount);
                for (let i = 0; i < thisCount; i++) {
                    newIndices[i] = indices[i];
                }
            }
            else {
                newIndices = new (Ctor as DataTypedArrayConstructor)(
                    (indices as DataTypedArray).buffer, 0, thisCount
                );
            }
        }
        else {
            const Ctor = getIndicesCtor(this._rawCount);
            newIndices = new Ctor(this.count());
            for (let i = 0; i < newIndices.length; i++) {
                newIndices[i] = i;
            }
        }

        return newIndices;
    }

    /**
     * Data filter.
     */
    filter(
        dims: DimensionIndex[],
        cb: FilterCb
    ): DataStore {
        if (!this._count) {
            return this;
        }

        const newStore = this.clone();

        const count = newStore.count();
        const Ctor = getIndicesCtor(newStore._rawCount);
        const newIndices = new Ctor(count);
        const value = [];
        const dimSize = dims.length;

        let offset = 0;
        const dim0 = dims[0];
        const chunks = newStore._chunks;

        for (let i = 0; i < count; i++) {
            let keep;
            const rawIdx = newStore.getRawIndex(i);
            // Simple optimization
            if (dimSize === 0) {
                keep = (cb as FilterCb0)(i);
            }
            else if (dimSize === 1) {
                const val = chunks[dim0][rawIdx];
                keep = (cb as FilterCb1)(val, i);
            }
            else {
                let k = 0;
                for (; k < dimSize; k++) {
                    value[k] = chunks[dims[k]][rawIdx];
                }
                value[k] = i;
                keep = (cb as FilterCb).apply(null, value);
            }
            if (keep) {
                newIndices[offset++] = rawIdx;
            }
        }

        // Set indices after filtered.
        if (offset < count) {
            newStore._indices = newIndices;
        }
        newStore._count = offset;
        // Reset data extent
        newStore._extent = [];

        newStore._updateGetRawIdx();

        return newStore;
    }

    /**
     * Select data in range. (For optimization of filter)
     * (Manually inline code, support 5 million data filtering in data zoom.)
     */
    selectRange(range: {[dimIdx: number]: [number, number]}): DataStore {
        const newStore = this.clone();

        const len = newStore._count;

        if (!len) {
            return this;
        }

        const dims = keys(range);
        const dimSize = dims.length;
        if (!dimSize) {
            return this;
        }

        const originalCount = newStore.count();
        const Ctor = getIndicesCtor(newStore._rawCount);
        const newIndices = new Ctor(originalCount);

        let offset = 0;
        const dim0 = dims[0];

        const min = range[dim0][0];
        const max = range[dim0][1];
        const storeArr = newStore._chunks;

        let quickFinished = false;
        if (!newStore._indices) {
            // Extreme optimization for common case. About 2x faster in chrome.
            let idx = 0;
            if (dimSize === 1) {
                const dimStorage = storeArr[dims[0]];
                for (let i = 0; i < len; i++) {
                    const val = dimStorage[i];
                    // NaN will not be filtered. Consider the case, in line chart, empty
                    // value indicates the line should be broken. But for the case like
                    // scatter plot, a data item with empty value will not be rendered,
                    // but the axis extent may be effected if some other dim of the data
                    // item has value. Fortunately it is not a significant negative effect.
                    if (
                        (val >= min && val <= max) || isNaN(val as any)
                    ) {
                        newIndices[offset++] = idx;
                    }
                    idx++;
                }
                quickFinished = true;
            }
            else if (dimSize === 2) {
                const dimStorage = storeArr[dims[0]];
                const dimStorage2 = storeArr[dims[1]];
                const min2 = range[dims[1]][0];
                const max2 = range[dims[1]][1];
                for (let i = 0; i < len; i++) {
                    const val = dimStorage[i];
                    const val2 = dimStorage2[i];
                    // Do not filter NaN, see comment above.
                    if ((
                            (val >= min && val <= max) || isNaN(val as any)
                        )
                        && (
                            (val2 >= min2 && val2 <= max2) || isNaN(val2 as any)
                        )
                    ) {
                        newIndices[offset++] = idx;
                    }
                    idx++;
                }
                quickFinished = true;
            }
        }
        if (!quickFinished) {
            if (dimSize === 1) {
                for (let i = 0; i < originalCount; i++) {
                    const rawIndex = newStore.getRawIndex(i);
                    const val = storeArr[dims[0]][rawIndex];
                    // Do not filter NaN, see comment above.
                    if (
                        (val >= min && val <= max) || isNaN(val as any)
                    ) {
                        newIndices[offset++] = rawIndex;
                    }
                }
            }
            else {
                for (let i = 0; i < originalCount; i++) {
                    let keep = true;
                    const rawIndex = newStore.getRawIndex(i);
                    for (let k = 0; k < dimSize; k++) {
                        const dimk = dims[k];
                        const val = storeArr[dimk][rawIndex];
                        // Do not filter NaN, see comment above.
                        if (val < range[dimk][0] || val > range[dimk][1]) {
                            keep = false;
                        }
                    }
                    if (keep) {
                        newIndices[offset++] = newStore.getRawIndex(i);
                    }
                }
            }
        }

        // Set indices after filtered.
        if (offset < originalCount) {
            newStore._indices = newIndices;
        }
        newStore._count = offset;
        // Reset data extent
        newStore._extent = [];

        newStore._updateGetRawIdx();

        return newStore;
    }

    // /**
    //  * Data mapping to a plain array
    //  */
    // mapArray(dims: DimensionIndex[], cb: MapArrayCb): any[] {
    //     const result: any[] = [];
    //     this.each(dims, function () {
    //         result.push(cb && (cb as MapArrayCb).apply(null, arguments));
    //     });
    //     return result;
    // }

    /**
     * Data mapping to a new List with given dimensions
     */
    map(dims: DimensionIndex[], cb: MapCb): DataStore {
        // TODO only clone picked chunks.
        const target = this.clone(dims);
        this._updateDims(target, dims, cb);
        return target;
    }

    /**
     * @caution Danger!! Only used in dataStack.
     */
    modify(dims: DimensionIndex[], cb: MapCb) {
        this._updateDims(this, dims, cb);
    }

    private _updateDims(
        target: DataStore,
        dims: DimensionIndex[],
        cb: MapCb
    ) {
        const targetChunks = target._chunks;

        const tmpRetValue = [];
        const dimSize = dims.length;
        const dataCount = target.count();
        const values = [];
        const rawExtent = target._rawExtent;

        for (let i = 0; i < dims.length; i++) {
            rawExtent[dims[i]] = getInitialExtent();
        }

        for (let dataIndex = 0; dataIndex < dataCount; dataIndex++) {
            const rawIndex = target.getRawIndex(dataIndex);

            for (let k = 0; k < dimSize; k++) {
                values[k] = targetChunks[dims[k]][rawIndex];
            }
            values[dimSize] = dataIndex;

            let retValue = cb && cb.apply(null, values);
            if (retValue != null) {
                // a number or string (in oridinal dimension)?
                if (typeof retValue !== 'object') {
                    tmpRetValue[0] = retValue;
                    retValue = tmpRetValue;
                }

                for (let i = 0; i < retValue.length; i++) {
                    const dim = dims[i];
                    const val = retValue[i];
                    const rawExtentOnDim = rawExtent[dim];

                    const dimStore = targetChunks[dim];
                    if (dimStore) {
                        (dimStore as ParsedValue[])[rawIndex] = val;
                    }

                    if (val < rawExtentOnDim[0]) {
                        rawExtentOnDim[0] = val as number;
                    }
                    if (val > rawExtentOnDim[1]) {
                        rawExtentOnDim[1] = val as number;
                    }
                }
            }
        }
    }

    /**
     * Large data down sampling using largest-triangle-three-buckets
     * @param {string} valueDimension
     * @param {number} targetCount
     */
    lttbDownSample(
        valueDimension: DimensionIndex,
        rate: number
    ): DataStore {
        const target = this.clone([valueDimension], true);
        const targetStorage = target._chunks;
        const dimStore = targetStorage[valueDimension];
        const len = this.count();

        let sampledIndex = 0;

        const frameSize = Math.floor(1 / rate);

        let currentRawIndex = this.getRawIndex(0);
        let maxArea;
        let area;
        let nextRawIndex;

        const newIndices = new (getIndicesCtor(this._rawCount))(Math.min((Math.ceil(len / frameSize) + 2) * 2, len));

        // First frame use the first data.
        newIndices[sampledIndex++] = currentRawIndex;
        for (let i = 1; i < len - 1; i += frameSize) {
            const nextFrameStart = Math.min(i + frameSize, len - 1);
            const nextFrameEnd = Math.min(i + frameSize * 2, len);

            const avgX = (nextFrameEnd + nextFrameStart) / 2;
            let avgY = 0;

            for (let idx = nextFrameStart; idx < nextFrameEnd; idx++) {
                const rawIndex = this.getRawIndex(idx);
                const y = dimStore[rawIndex] as number;
                if (isNaN(y)) {
                    continue;
                }
                avgY += y as number;
            }
            avgY /= (nextFrameEnd - nextFrameStart);

            const frameStart = i;
            const frameEnd = Math.min(i + frameSize, len);

            const pointAX = i - 1;
            const pointAY = dimStore[currentRawIndex] as number;

            maxArea = -1;

            nextRawIndex = frameStart;

            let firstNaNIndex = -1;
            let countNaN = 0;
            // Find a point from current frame that construct a triangel with largest area with previous selected point
            // And the average of next frame.
            for (let idx = frameStart; idx < frameEnd; idx++) {
                const rawIndex = this.getRawIndex(idx);
                const y = dimStore[rawIndex] as number;
                if (isNaN(y)) {
                    countNaN++;
                    if (firstNaNIndex < 0) {
                        firstNaNIndex = rawIndex;
                    }
                    continue;
                }
                // Calculate triangle area over three buckets
                area = Math.abs((pointAX - avgX) * (y - pointAY)
                    - (pointAX - idx) * (avgY - pointAY)
                );
                if (area > maxArea) {
                    maxArea = area;
                    nextRawIndex = rawIndex; // Next a is this b
                }
            }

            if (countNaN > 0 && countNaN < frameEnd - frameStart) {
                // Append first NaN point in every bucket.
                // It is necessary to ensure the correct order of indices.
                newIndices[sampledIndex++] = Math.min(firstNaNIndex, nextRawIndex);
                nextRawIndex = Math.max(firstNaNIndex, nextRawIndex);
            }

            newIndices[sampledIndex++] = nextRawIndex;

            currentRawIndex = nextRawIndex; // This a is the next a (chosen b)
        }

        // First frame use the last data.
        newIndices[sampledIndex++] = this.getRawIndex(len - 1);
        target._count = sampledIndex;
        target._indices = newIndices;

        target.getRawIndex = this._getRawIdx;
        return target;
    }


    /**
     * Large data down sampling on given dimension
     * @param sampleIndex Sample index for name and id
     */
    downSample(
        dimension: DimensionIndex,
        rate: number,
        sampleValue: (frameValues: ArrayLike<ParsedValue>) => ParsedValueNumeric,
        sampleIndex: (frameValues: ArrayLike<ParsedValue>, value: ParsedValueNumeric) => number
    ): DataStore {
        const target = this.clone([dimension], true);
        const targetStorage = target._chunks;

        const frameValues = [];
        let frameSize = Math.floor(1 / rate);

        const dimStore = targetStorage[dimension];
        const len = this.count();
        const rawExtentOnDim = target._rawExtent[dimension] = getInitialExtent();

        const newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize));

        let offset = 0;
        for (let i = 0; i < len; i += frameSize) {
            // Last frame
            if (frameSize > len - i) {
                frameSize = len - i;
                frameValues.length = frameSize;
            }
            for (let k = 0; k < frameSize; k++) {
                const dataIdx = this.getRawIndex(i + k);
                frameValues[k] = dimStore[dataIdx];
            }
            const value = sampleValue(frameValues);
            const sampleFrameIdx = this.getRawIndex(
                Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)
            );
            // Only write value on the filtered data
            (dimStore as number[])[sampleFrameIdx] = value;

            if (value < rawExtentOnDim[0]) {
                rawExtentOnDim[0] = value;
            }
            if (value > rawExtentOnDim[1]) {
                rawExtentOnDim[1] = value;
            }

            newIndices[offset++] = sampleFrameIdx;
        }

        target._count = offset;
        target._indices = newIndices;

        target._updateGetRawIdx();

        return target;
    }

    /**
     * Data iteration
     * @param ctx default this
     * @example
     *  list.each('x', function (x, idx) {});
     *  list.each(['x', 'y'], function (x, y, idx) {});
     *  list.each(function (idx) {})
     */
    each(dims: DimensionIndex[], cb: EachCb): void {
        if (!this._count) {
            return;
        }
        const dimSize = dims.length;
        const chunks = this._chunks;

        for (let i = 0, len = this.count(); i < len; i++) {
            const rawIdx = this.getRawIndex(i);
            // Simple optimization
            switch (dimSize) {
                case 0:
                    (cb as EachCb0)(i);
                    break;
                case 1:
                    (cb as EachCb1)(chunks[dims[0]][rawIdx], i);
                    break;
                case 2:
                    (cb as EachCb2)(
                        chunks[dims[0]][rawIdx], chunks[dims[1]][rawIdx], i
                    );
                    break;
                default:
                    let k = 0;
                    const value = [];
                    for (; k < dimSize; k++) {
                        value[k] = chunks[dims[k]][rawIdx];
                    }
                    // Index
                    value[k] = i;
                    (cb as EachCb).apply(null, value);
            }
        }
    }

    /**
     * Get extent of data in one dimension
     */
    getDataExtent(dim: DimensionIndex): [number, number] {
        // Make sure use concrete dim as cache name.
        const dimData = this._chunks[dim];
        const initialExtent = getInitialExtent();

        if (!dimData) {
            return initialExtent;
        }

        // Make more strict checkings to ensure hitting cache.
        const currEnd = this.count();

        // Consider the most cases when using data zoom, `getDataExtent`
        // happened before filtering. We cache raw extent, which is not
        // necessary to be cleared and recalculated when restore data.
        const useRaw = !this._indices;
        let dimExtent: [number, number];

        if (useRaw) {
            return this._rawExtent[dim].slice() as [number, number];
        }
        dimExtent = this._extent[dim];
        if (dimExtent) {
            return dimExtent.slice() as [number, number];
        }
        dimExtent = initialExtent;

        let min = dimExtent[0];
        let max = dimExtent[1];

        for (let i = 0; i < currEnd; i++) {
            const rawIdx = this.getRawIndex(i);
            const value = dimData[rawIdx] as ParsedValueNumeric;
            value < min && (min = value);
            value > max && (max = value);
        }

        dimExtent = [min, max];

        this._extent[dim] = dimExtent;

        return dimExtent;
    }

    /**
     * Get raw data index.
     * Do not initialize.
     * Default `getRawIndex`. And it can be changed.
     */
    getRawIndex: (idx: number) => number;

    /**
     * Get raw data item
     */
    getRawDataItem(idx: number): OptionDataItem {
        const rawIdx = this.getRawIndex(idx);
        if (!this._provider.persistent) {
            const val = [];
            const chunks = this._chunks;
            for (let i = 0; i < chunks.length; i++) {
                val.push(chunks[i][rawIdx]);
            }
            return val;
        }
        else {
            return this._provider.getItem(rawIdx);
        }
    }

    /**
     * Clone shallow.
     *
     * @param clonedDims Determine which dims to clone. Will share the data if not specified.
     */
    clone(clonedDims?: DimensionIndex[], ignoreIndices?: boolean): DataStore {
        const target = new DataStore();
        const chunks = this._chunks;
        const clonedDimsMap = clonedDims && reduce(clonedDims, (obj, dimIdx) => {
            obj[dimIdx] = true;
            return obj;
        }, {} as Record<DimensionIndex, boolean>);

        if (clonedDimsMap) {
            for (let i = 0; i < chunks.length; i++) {
                // Not clone if dim is not picked.
                target._chunks[i] = !clonedDimsMap[i] ? chunks[i] : cloneChunk(chunks[i]);
            }
        }
        else {
            target._chunks = chunks;
        }
        this._copyCommonProps(target);

        if (!ignoreIndices) {
            target._indices = this._cloneIndices();
        }
        target._updateGetRawIdx();
        return target;
    }

    private _copyCommonProps(target: DataStore): void {
        target._count = this._count;
        target._rawCount = this._rawCount;
        target._provider = this._provider;
        target._dimensions = this._dimensions;

        target._extent = clone(this._extent);
        target._rawExtent = clone(this._rawExtent);
    }

    private _cloneIndices(): DataStore['_indices'] {
        if (this._indices) {
            const Ctor = this._indices.constructor as DataArrayLikeConstructor;
            let indices;
            if (Ctor === Array) {
                const thisCount = this._indices.length;
                indices = new Ctor(thisCount);
                for (let i = 0; i < thisCount; i++) {
                    indices[i] = this._indices[i];
                }
            }
            else {
                indices = new (Ctor as DataTypedArrayConstructor)(this._indices);
            }
            return indices;
        }
        return null;
    }

    private _getRawIdxIdentity(idx: number): number {
        return idx;
    }
    private _getRawIdx(idx: number): number {
        if (idx < this._count && idx >= 0) {
            return this._indices[idx];
        }
        return -1;
    }

    private _updateGetRawIdx(): void {
        this.getRawIndex = this._indices ? this._getRawIdx : this._getRawIdxIdentity;
    }

    private static internalField = (function () {

        function getDimValueSimply(
            this: DataStore, dataItem: any, property: string, dataIndex: number, dimIndex: number
        ): ParsedValue {
            return parseDataValue(dataItem[dimIndex], this._dimensions[dimIndex]);
        }

        defaultDimValueGetters = {

            arrayRows: getDimValueSimply,

            objectRows(
                this: DataStore, dataItem: any, property: string, dataIndex: number, dimIndex: number
            ): ParsedValue {
                return parseDataValue(dataItem[property], this._dimensions[dimIndex]);
            },

            keyedColumns: getDimValueSimply,

            original(
                this: DataStore, dataItem: any, property: string, dataIndex: number, dimIndex: number
            ): ParsedValue {
                // Performance sensitive, do not use modelUtil.getDataItemValue.
                // If dataItem is an plain object with no value field, the let `value`
                // will be assigned with the object, but it will be tread correctly
                // in the `convertValue`.
                const value = dataItem && (dataItem.value == null ? dataItem : dataItem.value);

                return parseDataValue(
                    (value instanceof Array)
                        ? value[dimIndex]
                        // If value is a single number or something else not array.
                        : value,
                    this._dimensions[dimIndex]
                );
            },

            typedArray: function (
                this: DataStore, dataItem: any, property: string, dataIndex: number, dimIndex: number
            ): ParsedValue {
                return dataItem[dimIndex];
            }

        };

    })();
}

export default DataStore;
