/*
* 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 {makeInner, getDataItemValue, queryReferringComponents, SINGLE_REFERRING} from '../../util/model';
import {
    createHashMap,
    each,
    isArray,
    isString,
    isObject,
    isTypedArray,
    HashMap
} from 'zrender/src/core/util';
import { Source } from '../Source';

import {
    SOURCE_FORMAT_ORIGINAL,
    SOURCE_FORMAT_ARRAY_ROWS,
    SOURCE_FORMAT_OBJECT_ROWS,
    SERIES_LAYOUT_BY_ROW,
    SOURCE_FORMAT_KEYED_COLUMNS,
    DimensionName,
    OptionSourceDataArrayRows,
    OptionDataValue,
    OptionSourceDataKeyedColumns,
    OptionSourceDataOriginal,
    OptionSourceDataObjectRows,
    OptionEncode,
    DimensionIndex,
    SeriesEncodableModel
} from '../../util/types';
import { DatasetModel } from '../../component/dataset/install';
import SeriesModel from '../../model/Series';
import GlobalModel from '../../model/Global';
import { CoordDimensionDefinition } from './createDimensions';

// The result of `guessOrdinal`.
export const BE_ORDINAL = {
    Must: 1, // Encounter string but not '-' and not number-like.
    Might: 2, // Encounter string but number-like.
    Not: 3 // Other cases
};
type BeOrdinalValue = (typeof BE_ORDINAL)[keyof typeof BE_ORDINAL];

const innerGlobalModel = makeInner<{
    datasetMap: HashMap<DatasetRecord, string>
}, GlobalModel>();


interface DatasetRecord {
    categoryWayDim: number;
    valueWayDim: number;
}

type SeriesEncodeInternal = {
    [key in keyof OptionEncode]: DimensionIndex[];
};

/**
 * MUST be called before mergeOption of all series.
 */
export function resetSourceDefaulter(ecModel: GlobalModel): void {
    // `datasetMap` is used to make default encode.
    innerGlobalModel(ecModel).datasetMap = createHashMap();
}

/**
 * [The strategy of the arrengment of data dimensions for dataset]:
 * "value way": all axes are non-category axes. So series one by one take
 *     several (the number is coordSysDims.length) dimensions from dataset.
 *     The result of data arrengment of data dimensions like:
 *     | ser0_x | ser0_y | ser1_x | ser1_y | ser2_x | ser2_y |
 * "category way": at least one axis is category axis. So the the first data
 *     dimension is always mapped to the first category axis and shared by
 *     all of the series. The other data dimensions are taken by series like
 *     "value way" does.
 *     The result of data arrengment of data dimensions like:
 *     | ser_shared_x | ser0_y | ser1_y | ser2_y |
 *
 * @return encode Never be `null/undefined`.
 */
export function makeSeriesEncodeForAxisCoordSys(
    coordDimensions: (DimensionName | CoordDimensionDefinition)[],
    seriesModel: SeriesModel,
    source: Source
): SeriesEncodeInternal {
    const encode: SeriesEncodeInternal = {};

    const datasetModel = querySeriesUpstreamDatasetModel(seriesModel);
    // Currently only make default when using dataset, util more reqirements occur.
    if (!datasetModel || !coordDimensions) {
        return encode;
    }

    const encodeItemName: DimensionIndex[] = [];
    const encodeSeriesName: DimensionIndex[] = [];

    const ecModel = seriesModel.ecModel;
    const datasetMap = innerGlobalModel(ecModel).datasetMap;
    const key = datasetModel.uid + '_' + source.seriesLayoutBy;

    let baseCategoryDimIndex: number;
    let categoryWayValueDimStart;
    coordDimensions = coordDimensions.slice();
    each(coordDimensions, function (coordDimInfoLoose, coordDimIdx) {
        const coordDimInfo: CoordDimensionDefinition = isObject(coordDimInfoLoose)
            ? coordDimInfoLoose
            : (coordDimensions[coordDimIdx] = { name: coordDimInfoLoose as DimensionName });
        if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) {
            baseCategoryDimIndex = coordDimIdx;
            categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimInfo);
        }
        encode[coordDimInfo.name] = [];
    });

    const datasetRecord = datasetMap.get(key)
        || datasetMap.set(key, {categoryWayDim: categoryWayValueDimStart, valueWayDim: 0});

    // TODO
    // Auto detect first time axis and do arrangement.
    each(coordDimensions, function (coordDimInfo: CoordDimensionDefinition, coordDimIdx) {
        const coordDimName = coordDimInfo.name;
        const count = getDataDimCountOnCoordDim(coordDimInfo);

        // In value way.
        if (baseCategoryDimIndex == null) {
            const start = datasetRecord.valueWayDim;
            pushDim(encode[coordDimName], start, count);
            pushDim(encodeSeriesName, start, count);
            datasetRecord.valueWayDim += count;

            // ??? TODO give a better default series name rule?
            // especially when encode x y specified.
            // consider: when mutiple series share one dimension
            // category axis, series name should better use
            // the other dimsion name. On the other hand, use
            // both dimensions name.
        }
        // In category way, the first category axis.
        else if (baseCategoryDimIndex === coordDimIdx) {
            pushDim(encode[coordDimName], 0, count);
            pushDim(encodeItemName, 0, count);
        }
        // In category way, the other axis.
        else {
            const start = datasetRecord.categoryWayDim;
            pushDim(encode[coordDimName], start, count);
            pushDim(encodeSeriesName, start, count);
            datasetRecord.categoryWayDim += count;
        }
    });

    function pushDim(dimIdxArr: DimensionIndex[], idxFrom: number, idxCount: number) {
        for (let i = 0; i < idxCount; i++) {
            dimIdxArr.push(idxFrom + i);
        }
    }

    function getDataDimCountOnCoordDim(coordDimInfo: CoordDimensionDefinition) {
        const dimsDef = coordDimInfo.dimsDef;
        return dimsDef ? dimsDef.length : 1;
    }

    encodeItemName.length && (encode.itemName = encodeItemName);
    encodeSeriesName.length && (encode.seriesName = encodeSeriesName);

    return encode;
}

/**
 * Work for data like [{name: ..., value: ...}, ...].
 *
 * @return encode Never be `null/undefined`.
 */
export function makeSeriesEncodeForNameBased(
    seriesModel: SeriesModel,
    source: Source,
    dimCount: number
): SeriesEncodeInternal {
    const encode: SeriesEncodeInternal = {};

    const datasetModel = querySeriesUpstreamDatasetModel(seriesModel);
    // Currently only make default when using dataset, util more reqirements occur.
    if (!datasetModel) {
        return encode;
    }

    const sourceFormat = source.sourceFormat;
    const dimensionsDefine = source.dimensionsDefine;

    let potentialNameDimIndex;
    if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
        each(dimensionsDefine, function (dim, idx) {
            if ((isObject(dim) ? dim.name : dim) === 'name') {
                potentialNameDimIndex = idx;
            }
        });
    }

    type IdxResult = { v: number, n: number };

    const idxResult = (function () {

        const idxRes0 = {} as IdxResult;
        const idxRes1 = {} as IdxResult;
        const guessRecords = [];

        // 5 is an experience value.
        for (let i = 0, len = Math.min(5, dimCount); i < len; i++) {
            const guessResult = doGuessOrdinal(
                source.data, sourceFormat, source.seriesLayoutBy,
                dimensionsDefine, source.startIndex, i
            );
            guessRecords.push(guessResult);
            const isPureNumber = guessResult === BE_ORDINAL.Not;

            // [Strategy of idxRes0]: find the first BE_ORDINAL.Not as the value dim,
            // and then find a name dim with the priority:
            // "BE_ORDINAL.Might|BE_ORDINAL.Must" > "other dim" > "the value dim itself".
            if (isPureNumber && idxRes0.v == null && i !== potentialNameDimIndex) {
                idxRes0.v = i;
            }
            if (idxRes0.n == null
                || (idxRes0.n === idxRes0.v)
                || (!isPureNumber && guessRecords[idxRes0.n] === BE_ORDINAL.Not)
            ) {
                idxRes0.n = i;
            }
            if (fulfilled(idxRes0) && guessRecords[idxRes0.n] !== BE_ORDINAL.Not) {
                return idxRes0;
            }

            // [Strategy of idxRes1]: if idxRes0 not satisfied (that is, no BE_ORDINAL.Not),
            // find the first BE_ORDINAL.Might as the value dim,
            // and then find a name dim with the priority:
            // "other dim" > "the value dim itself".
            // That is for backward compat: number-like (e.g., `'3'`, `'55'`) can be
            // treated as number.
            if (!isPureNumber) {
                if (guessResult === BE_ORDINAL.Might && idxRes1.v == null && i !== potentialNameDimIndex) {
                    idxRes1.v = i;
                }
                if (idxRes1.n == null || (idxRes1.n === idxRes1.v)) {
                    idxRes1.n = i;
                }
            }
        }

        function fulfilled(idxResult: IdxResult) {
            return idxResult.v != null && idxResult.n != null;
        }

        return fulfilled(idxRes0) ? idxRes0 : fulfilled(idxRes1) ? idxRes1 : null;
    })();

    if (idxResult) {
        encode.value = [idxResult.v];
        // `potentialNameDimIndex` has highest priority.
        const nameDimIndex = potentialNameDimIndex != null ? potentialNameDimIndex : idxResult.n;
        // By default, label use itemName in charts.
        // So we dont set encodeLabel here.
        encode.itemName = [nameDimIndex];
        encode.seriesName = [nameDimIndex];
    }

    return encode;
}

/**
 * @return If return null/undefined, indicate that should not use datasetModel.
 */
export function querySeriesUpstreamDatasetModel(
    seriesModel: SeriesEncodableModel
): DatasetModel {
    // Caution: consider the scenario:
    // A dataset is declared and a series is not expected to use the dataset,
    // and at the beginning `setOption({series: { noData })` (just prepare other
    // option but no data), then `setOption({series: {data: [...]}); In this case,
    // the user should set an empty array to avoid that dataset is used by default.
    const thisData = seriesModel.get('data', true);
    if (!thisData) {
        return queryReferringComponents(
            seriesModel.ecModel,
            'dataset',
            {
                index: seriesModel.get('datasetIndex', true),
                id: seriesModel.get('datasetId', true)
            },
            SINGLE_REFERRING
        ).models[0] as DatasetModel;
    }
}

/**
 * @return Always return an array event empty.
 */
export function queryDatasetUpstreamDatasetModels(
    datasetModel: DatasetModel
): DatasetModel[] {
    // Only these attributes declared, we by defualt reference to `datasetIndex: 0`.
    // Otherwise, no reference.
    if (!datasetModel.get('transform', true)
        && !datasetModel.get('fromTransformResult', true)
    ) {
        return [];
    }

    return queryReferringComponents(
        datasetModel.ecModel,
        'dataset',
        {
            index: datasetModel.get('fromDatasetIndex', true),
            id: datasetModel.get('fromDatasetId', true)
        },
        SINGLE_REFERRING
    ).models as DatasetModel[];
}

/**
 * The rule should not be complex, otherwise user might not
 * be able to known where the data is wrong.
 * The code is ugly, but how to make it neat?
 */
export function guessOrdinal(source: Source, dimIndex: DimensionIndex): BeOrdinalValue {
    return doGuessOrdinal(
        source.data,
        source.sourceFormat,
        source.seriesLayoutBy,
        source.dimensionsDefine,
        source.startIndex,
        dimIndex
    );
}

// dimIndex may be overflow source data.
// return {BE_ORDINAL}
function doGuessOrdinal(
    data: Source['data'],
    sourceFormat: Source['sourceFormat'],
    seriesLayoutBy: Source['seriesLayoutBy'],
    dimensionsDefine: Source['dimensionsDefine'],
    startIndex: Source['startIndex'],
    dimIndex: DimensionIndex
): BeOrdinalValue {
    let result;
    // Experience value.
    const maxLoop = 5;

    if (isTypedArray(data)) {
        return BE_ORDINAL.Not;
    }

    // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine
    // always exists in source.
    let dimName;
    let dimType;
    if (dimensionsDefine) {
        const dimDefItem = dimensionsDefine[dimIndex];
        if (isObject(dimDefItem)) {
            dimName = dimDefItem.name;
            dimType = dimDefItem.type;
        }
        else if (isString(dimDefItem)) {
            dimName = dimDefItem;
        }
    }

    if (dimType != null) {
        return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not;
    }

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
        const dataArrayRows = data as OptionSourceDataArrayRows;
        if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
            const sample = dataArrayRows[dimIndex];
            for (let i = 0; i < (sample || []).length && i < maxLoop; i++) {
                if ((result = detectValue(sample[startIndex + i])) != null) {
                    return result;
                }
            }
        }
        else {
            for (let i = 0; i < dataArrayRows.length && i < maxLoop; i++) {
                const row = dataArrayRows[startIndex + i];
                if (row && (result = detectValue(row[dimIndex])) != null) {
                    return result;
                }
            }
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
        const dataObjectRows = data as OptionSourceDataObjectRows;
        if (!dimName) {
            return BE_ORDINAL.Not;
        }
        for (let i = 0; i < dataObjectRows.length && i < maxLoop; i++) {
            const item = dataObjectRows[i];
            if (item && (result = detectValue(item[dimName])) != null) {
                return result;
            }
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
        const dataKeyedColumns = data as OptionSourceDataKeyedColumns;
        if (!dimName) {
            return BE_ORDINAL.Not;
        }
        const sample = dataKeyedColumns[dimName];
        if (!sample || isTypedArray(sample)) {
            return BE_ORDINAL.Not;
        }
        for (let i = 0; i < sample.length && i < maxLoop; i++) {
            if ((result = detectValue(sample[i])) != null) {
                return result;
            }
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
        const dataOriginal = data as OptionSourceDataOriginal;
        for (let i = 0; i < dataOriginal.length && i < maxLoop; i++) {
            const item = dataOriginal[i];
            const val = getDataItemValue(item);
            if (!isArray(val)) {
                return BE_ORDINAL.Not;
            }
            if ((result = detectValue(val[dimIndex])) != null) {
                return result;
            }
        }
    }

    function detectValue(val: OptionDataValue): BeOrdinalValue {
        const beStr = isString(val);
        // Consider usage convenience, '1', '2' will be treated as "number".
        // `isFinit('')` get `true`.
        if (val != null && isFinite(val as number) && val !== '') {
            return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not;
        }
        else if (beStr && val !== '-') {
            return BE_ORDINAL.Must;
        }
    }

    return BE_ORDINAL.Not;
}
