/*
* 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 {
    isTypedArray, HashMap, clone, createHashMap, isArray, isObject, isArrayLike,
    hasOwn, assert, each, map, isNumber, isString
} from 'zrender/src/core/util';
import {
    SourceFormat, SeriesLayoutBy, DimensionDefinition,
    OptionEncodeValue, OptionSourceData,
    SOURCE_FORMAT_ORIGINAL,
    SERIES_LAYOUT_BY_COLUMN,
    SOURCE_FORMAT_UNKNOWN,
    SOURCE_FORMAT_KEYED_COLUMNS,
    SOURCE_FORMAT_TYPED_ARRAY,
    DimensionName,
    OptionSourceHeader,
    DimensionDefinitionLoose,
    SOURCE_FORMAT_ARRAY_ROWS,
    SOURCE_FORMAT_OBJECT_ROWS,
    Dictionary,
    OptionSourceDataObjectRows,
    OptionDataValue,
    OptionSourceDataArrayRows,
    SERIES_LAYOUT_BY_ROW,
    OptionSourceDataOriginal,
    OptionSourceDataKeyedColumns
} from '../util/types';
import { DatasetOption } from '../component/dataset/install';
import { getDataItemValue } from '../util/model';
import { BE_ORDINAL, guessOrdinal } from './helper/sourceHelper';

/**
 * [sourceFormat]
 *
 * + "original":
 * This format is only used in series.data, where
 * itemStyle can be specified in data item.
 *
 * + "arrayRows":
 * [
 *     ['product', 'score', 'amount'],
 *     ['Matcha Latte', 89.3, 95.8],
 *     ['Milk Tea', 92.1, 89.4],
 *     ['Cheese Cocoa', 94.4, 91.2],
 *     ['Walnut Brownie', 85.4, 76.9]
 * ]
 *
 * + "objectRows":
 * [
 *     {product: 'Matcha Latte', score: 89.3, amount: 95.8},
 *     {product: 'Milk Tea', score: 92.1, amount: 89.4},
 *     {product: 'Cheese Cocoa', score: 94.4, amount: 91.2},
 *     {product: 'Walnut Brownie', score: 85.4, amount: 76.9}
 * ]
 *
 * + "keyedColumns":
 * {
 *     'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'],
 *     'count': [823, 235, 1042, 988],
 *     'score': [95.8, 81.4, 91.2, 76.9]
 * }
 *
 * + "typedArray"
 *
 * + "unknown"
 */

export interface SourceMetaRawOption {
    seriesLayoutBy: SeriesLayoutBy;
    sourceHeader: OptionSourceHeader;
    dimensions: DimensionDefinitionLoose[];
}

// Prevent from `new Source()` external and circular reference.
export interface Source extends SourceImpl {};
// @inner
class SourceImpl {

    /**
     * Not null/undefined.
     */
    readonly data: OptionSourceData;

    /**
     * See also "detectSourceFormat".
     * Not null/undefined.
     */
    readonly sourceFormat: SourceFormat;

    /**
     * 'row' or 'column'
     * Not null/undefined.
     */
    readonly seriesLayoutBy: SeriesLayoutBy;

    /**
     * dimensions definition from:
     * (1) standalone defined in option prop `dimensions: [...]`
     * (2) detected from option data. See `determineSourceDimensions`.
     * If can not be detected (e.g., there is only pure data `[[11, 33], ...]`
     * `dimensionsDefine` will be null/undefined.
     */
    readonly dimensionsDefine: DimensionDefinition[];

    /**
     * Only make sense in `SOURCE_FORMAT_ARRAY_ROWS`.
     * That is the same as `sourceHeader: number`,
     * which means from which line the real data start.
     * Not null/undefined, uint.
     */
    readonly startIndex: number;

    /**
     * Dimension count detected from data. Only works when `dimensionDefine`
     * does not exists.
     * Can be null/undefined (when unknown), uint.
     */
    readonly dimensionsDetectedCount: number;

    /**
     * Raw props from user option.
     */
    readonly metaRawOption: SourceMetaRawOption;


    constructor(fields: {
        data: OptionSourceData,
        sourceFormat: SourceFormat, // default: SOURCE_FORMAT_UNKNOWN

        // Visit config are optional:
        seriesLayoutBy?: SeriesLayoutBy, // default: 'column'
        dimensionsDefine?: DimensionDefinition[],
        startIndex?: number, // default: 0
        dimensionsDetectedCount?: number,

        metaRawOption?: SourceMetaRawOption,

        // [Caveat]
        // This is the raw user defined `encode` in `series`.
        // If user not defined, DO NOT make a empty object or hashMap here.
        // An empty object or hashMap will prevent from auto generating encode.
        encodeDefine?: HashMap<OptionEncodeValue, DimensionName>
    }) {

        this.data = fields.data || (
            fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []
        );
        this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN;

        // Visit config
        this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN;
        this.startIndex = fields.startIndex || 0;
        this.dimensionsDetectedCount = fields.dimensionsDetectedCount;
        this.metaRawOption = fields.metaRawOption;

        const dimensionsDefine = this.dimensionsDefine = fields.dimensionsDefine;

        if (dimensionsDefine) {
            for (let i = 0; i < dimensionsDefine.length; i++) {
                const dim = dimensionsDefine[i];
                if (dim.type == null) {
                    if (guessOrdinal(this, i) === BE_ORDINAL.Must) {
                        dim.type = 'ordinal';
                    }
                }
            }
        }
    }

}

export function isSourceInstance(val: unknown): val is Source {
    return val instanceof SourceImpl;
}

/**
 * Create a source from option.
 * NOTE: Created source is immutable. Don't change any properties in it.
 */
export function createSource(
    sourceData: OptionSourceData,
    thisMetaRawOption: SourceMetaRawOption,
    // can be null. If not provided, auto detect it from `sourceData`.
    sourceFormat: SourceFormat
): Source {
    sourceFormat = sourceFormat || detectSourceFormat(sourceData);
    const seriesLayoutBy = thisMetaRawOption.seriesLayoutBy;
    const determined = determineSourceDimensions(
        sourceData,
        sourceFormat,
        seriesLayoutBy,
        thisMetaRawOption.sourceHeader,
        thisMetaRawOption.dimensions
    );
    const source = new SourceImpl({
        data: sourceData,
        sourceFormat: sourceFormat,

        seriesLayoutBy: seriesLayoutBy,
        dimensionsDefine: determined.dimensionsDefine,
        startIndex: determined.startIndex,
        dimensionsDetectedCount: determined.dimensionsDetectedCount,
        metaRawOption: clone(thisMetaRawOption)
    });

    return source;
}

/**
 * Wrap original series data for some compatibility cases.
 */
export function createSourceFromSeriesDataOption(data: OptionSourceData): Source {
    return new SourceImpl({
        data: data,
        sourceFormat: isTypedArray(data)
            ? SOURCE_FORMAT_TYPED_ARRAY
            : SOURCE_FORMAT_ORIGINAL
    });
}

/**
 * Clone source but excludes source data.
 */
export function cloneSourceShallow(source: Source): Source {
    return new SourceImpl({
        data: source.data,
        sourceFormat: source.sourceFormat,

        seriesLayoutBy: source.seriesLayoutBy,
        dimensionsDefine: clone(source.dimensionsDefine),
        startIndex: source.startIndex,
        dimensionsDetectedCount: source.dimensionsDetectedCount
    });
}

/**
 * Note: An empty array will be detected as `SOURCE_FORMAT_ARRAY_ROWS`.
 */
export function detectSourceFormat(data: DatasetOption['source']): SourceFormat {
    let sourceFormat: SourceFormat = SOURCE_FORMAT_UNKNOWN;

    if (isTypedArray(data)) {
        sourceFormat = SOURCE_FORMAT_TYPED_ARRAY;
    }
    else if (isArray(data)) {
        // FIXME Whether tolerate null in top level array?
        if (data.length === 0) {
            sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
        }

        for (let i = 0, len = data.length; i < len; i++) {
            const item = data[i];

            if (item == null) {
                continue;
            }
            else if (isArray(item)) {
                sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
                break;
            }
            else if (isObject(item)) {
                sourceFormat = SOURCE_FORMAT_OBJECT_ROWS;
                break;
            }
        }
    }
    else if (isObject(data)) {
        for (const key in data) {
            if (hasOwn(data, key) && isArrayLike((data as Dictionary<unknown>)[key])) {
                sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS;
                break;
            }
        }
    }

    return sourceFormat;
}

/**
 * Determine the source definitions from data standalone dimensions definitions
 * are not specified.
 */
function determineSourceDimensions(
    data: OptionSourceData,
    sourceFormat: SourceFormat,
    seriesLayoutBy: SeriesLayoutBy,
    sourceHeader: OptionSourceHeader,
    // standalone raw dimensions definition, like:
    // {
    //     dimensions: ['aa', 'bb', { name: 'cc', type: 'time' }]
    // }
    // in `dataset` or `series`
    dimensionsDefine: DimensionDefinitionLoose[]
): {
    // If the input `dimensionsDefine` is specified, return it.
    // Else determine dimensions from the input `data`.
    // If not determined, `dimensionsDefine` will be null/undefined.
    dimensionsDefine: Source['dimensionsDefine'];
    startIndex: Source['startIndex'];
    dimensionsDetectedCount: Source['dimensionsDetectedCount'];
} {
    let dimensionsDetectedCount;
    let startIndex: number;

    // PENDING: Could data be null/undefined here?
    // currently, if `dataset.source` not specified, error thrown.
    // if `series.data` not specified, nothing rendered without error thrown.
    // Should test these cases.
    if (!data) {
        return {
            dimensionsDefine: normalizeDimensionsOption(dimensionsDefine),
            startIndex,
            dimensionsDetectedCount
        };
    }

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
        const dataArrayRows = data as OptionSourceDataArrayRows;
        // Rule: Most of the first line are string: it is header.
        // Caution: consider a line with 5 string and 1 number,
        // it still can not be sure it is a head, because the
        // 5 string may be 5 values of category columns.
        if (sourceHeader === 'auto' || sourceHeader == null) {
            arrayRowsTravelFirst(function (val) {
                // '-' is regarded as null/undefined.
                if (val != null && val !== '-') {
                    if (isString(val)) {
                        startIndex == null && (startIndex = 1);
                    }
                    else {
                        startIndex = 0;
                    }
                }
            // 10 is an experience number, avoid long loop.
            }, seriesLayoutBy, dataArrayRows, 10);
        }
        else {
            startIndex = isNumber(sourceHeader) ? sourceHeader : sourceHeader ? 1 : 0;
        }

        if (!dimensionsDefine && startIndex === 1) {
            dimensionsDefine = [];
            arrayRowsTravelFirst(function (val, index) {
                dimensionsDefine[index] = (val != null ? val + '' : '') as DimensionName;
            }, seriesLayoutBy, dataArrayRows, Infinity);
        }

        dimensionsDetectedCount = dimensionsDefine
            ? dimensionsDefine.length
            : seriesLayoutBy === SERIES_LAYOUT_BY_ROW
            ? dataArrayRows.length
            : dataArrayRows[0]
            ? dataArrayRows[0].length
            : null;
    }
    else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
        if (!dimensionsDefine) {
            dimensionsDefine = objectRowsCollectDimensions(data as OptionSourceDataObjectRows);
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
        if (!dimensionsDefine) {
            dimensionsDefine = [];
            each(data as OptionSourceDataKeyedColumns, function (colArr, key) {
                dimensionsDefine.push(key);
            });
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
        const value0 = getDataItemValue((data as OptionSourceDataOriginal)[0]);
        dimensionsDetectedCount = isArray(value0) && value0.length || 1;
    }
    else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
        if (__DEV__) {
            assert(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.');
        }
    }

    return {
        startIndex: startIndex,
        dimensionsDefine: normalizeDimensionsOption(dimensionsDefine),
        dimensionsDetectedCount: dimensionsDetectedCount
    };
}

function objectRowsCollectDimensions(data: OptionSourceDataObjectRows): DimensionDefinitionLoose[] {
    let firstIndex = 0;
    let obj;
    while (firstIndex < data.length && !(obj = data[firstIndex++])) {} // jshint ignore: line
    if (obj) {
        const dimensions: DimensionDefinitionLoose[] = [];
        each(obj, function (value, key) {
            dimensions.push(key);
        });
        return dimensions;
    }
}

// Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'],
// which is reasonable. But dimension name is duplicated.
// Returns undefined or an array contains only object without null/undefined or string.
function normalizeDimensionsOption(dimensionsDefine: DimensionDefinitionLoose[]): DimensionDefinition[] {
    if (!dimensionsDefine) {
        // The meaning of null/undefined is different from empty array.
        return;
    }
    const nameMap = createHashMap<{ count: number }, string>();
    return map(dimensionsDefine, function (rawItem, index) {
        rawItem = isObject(rawItem) ? rawItem : { name: rawItem };
        // Other fields will be discarded.
        const item: DimensionDefinition = {
            name: rawItem.name,
            displayName: rawItem.displayName,
            type: rawItem.type
        };

        // User can set null in dimensions.
        // We don't auto specify name, otherwise a given name may
        // cause it to be referred unexpectedly.
        if (item.name == null) {
            return item;
        }

        // Also consider number form like 2012.
        item.name += '';
        // User may also specify displayName.
        // displayName will always exists except user not
        // specified or dim name is not specified or detected.
        // (A auto generated dim name will not be used as
        // displayName).
        if (item.displayName == null) {
            item.displayName = item.name;
        }

        const exist = nameMap.get(item.name);
        if (!exist) {
            nameMap.set(item.name, {count: 1});
        }
        else {
            item.name += '-' + exist.count++;
        }

        return item;
    });
}

function arrayRowsTravelFirst(
    cb: (val: OptionDataValue, idx: number) => void,
    seriesLayoutBy: SeriesLayoutBy,
    data: OptionSourceDataArrayRows,
    maxLoop: number
): void {
    if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
        for (let i = 0; i < data.length && i < maxLoop; i++) {
            cb(data[i] ? data[i][0] : null, i);
        }
    }
    else {
        const value0 = data[0] || [];
        for (let i = 0; i < value0.length && i < maxLoop; i++) {
            cb(value0[i], i);
        }
    }
}

export function shouldRetrieveDataByName(source: Source): boolean {
    const sourceFormat = source.sourceFormat;
    return sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS;
}
