/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import * as zrUtil from 'zrender/src/core/util';
import env from 'zrender/src/core/env';
import * as modelUtil from '../util/model';
import {
    DataHost, DimensionName, StageHandlerProgressParams,
    SeriesOption, ZRColor, BoxLayoutOptionMixin,
    ScaleDataValue,
    Dictionary,
    OptionDataItemObject,
    SeriesDataType,
    SeriesEncodeOptionMixin,
    OptionEncodeValue,
    ColorBy,
    StatesOptionMixin
} from '../util/types';
import ComponentModel, { ComponentModelConstructor } from './Component';
import {PaletteMixin} from './mixin/palette';
import { DataFormatMixin } from '../model/mixin/dataFormat';
import Model from '../model/Model';
import {
    getLayoutParams,
    mergeLayoutParam,
    fetchLayoutMode
} from '../util/layout';
import {createTask} from '../core/task';
import GlobalModel from './Global';
import { CoordinateSystem } from '../coord/CoordinateSystem';
import { ExtendableConstructor, mountExtend, Constructor } from '../util/clazz';
import { PipelineContext, SeriesTaskContext, GeneralTask, OverallTask, SeriesTask } from '../core/Scheduler';
import LegendVisualProvider from '../visual/LegendVisualProvider';
import SeriesData from '../data/SeriesData';
import Axis from '../coord/Axis';
import type { BrushCommonSelectorsForSeries, BrushSelectableArea } from '../component/brush/selector';
import makeStyleMapper from './mixin/makeStyleMapper';
import { SourceManager } from '../data/helper/sourceManager';
import { Source } from '../data/Source';
import { defaultSeriesFormatTooltip } from '../component/tooltip/seriesFormatTooltip';
import {ECSymbol} from '../util/symbol';
import {Group} from '../util/graphic';
import {LegendIconParams} from '../component/legend/LegendModel';
import {dimPermutations} from '../component/marker/MarkAreaView';

const inner = modelUtil.makeInner<{
    data: SeriesData
    dataBeforeProcessed: SeriesData
    sourceManager: SourceManager
}, SeriesModel>();

function getSelectionKey(data: SeriesData, dataIndex: number): string {
    return data.getName(dataIndex) || data.getId(dataIndex);
}

export const SERIES_UNIVERSAL_TRANSITION_PROP = '__universalTransitionEnabled';

interface SeriesModel {
    /**
     * Convenient for override in extended class.
     * Implement it if needed.
     */
    preventIncremental(): boolean;
    /**
     * See tooltip.
     * Implement it if needed.
     * @return Point of tooltip. null/undefined can be returned.
     */
    getTooltipPosition(dataIndex: number): number[];

    /**
     * Get data indices for show tooltip content. See tooltip.
     * Implement it if needed.
     */
    getAxisTooltipData(
        dim: DimensionName[],
        value: ScaleDataValue,
        baseAxis: Axis
    ): {
        dataIndices: number[],
        nestestValue: any
    };

    /**
     * Get position for marker
     */
    getMarkerPosition(
        value: ScaleDataValue[],
        dims?: typeof dimPermutations[number],
        startingAtTick?: boolean
    ): number[];

    /**
     * Get legend icon symbol according to each series type
     */
    getLegendIcon(opt: LegendIconParams): ECSymbol | Group;

    /**
     * See `component/brush/selector.js`
     * Defined the brush selector for this series.
     */
    brushSelector(
        dataIndex: number,
        data: SeriesData,
        selectors: BrushCommonSelectorsForSeries,
        area: BrushSelectableArea
    ): boolean;

    enableAriaDecal(): void;
}

class SeriesModel<Opt extends SeriesOption = SeriesOption> extends ComponentModel<Opt> {

    // [Caution]: Because this class or desecendants can be used as `XXX.extend(subProto)`,
    // the class members must not be initialized in constructor or declaration place.
    // Otherwise there is bad case:
    //   class A {xxx = 1;}
    //   enableClassExtend(A);
    //   class B extends A {}
    //   var C = B.extend({xxx: 5});
    //   var c = new C();
    //   console.log(c.xxx); // expect 5 but always 1.

    // @readonly
    type: string;

    // Should be implenented in subclass.
    defaultOption: SeriesOption;

    // @readonly
    seriesIndex: number;

    // coodinateSystem will be injected in the echarts/CoordinateSystem
    coordinateSystem: CoordinateSystem;

    // Injected outside
    dataTask: SeriesTask;
    // Injected outside
    pipelineContext: PipelineContext;

    // ---------------------------------------
    // Props to tell visual/style.ts about how to do visual encoding.
    // ---------------------------------------
    // legend visual provider to the legend component
    legendVisualProvider: LegendVisualProvider;

    // Access path of style for visual
    visualStyleAccessPath: string;
    // Which property is treated as main color. Which can get from the palette.
    visualDrawType: 'fill' | 'stroke';
    // Style mapping rules.
    visualStyleMapper: ReturnType<typeof makeStyleMapper>;
    // If ignore style on data. It's only for global visual/style.ts
    // Enabled when series it self will handle it.
    ignoreStyleOnData: boolean;
    // If do symbol visual encoding
    hasSymbolVisual: boolean;
    // Default symbol type.
    defaultSymbol: string;
    // Symbol provide to legend.
    legendIcon: string;

    // It will be set temporary when cross series transition setting is from setOption.
    // TODO if deprecate further?
    [SERIES_UNIVERSAL_TRANSITION_PROP]: boolean;

    // ---------------------------------------
    // Props about data selection
    // ---------------------------------------
    private _selectedDataIndicesMap: Dictionary<number> = {};
    readonly preventUsingHoverLayer: boolean;

    static protoInitialize = (function () {
        const proto = SeriesModel.prototype;
        proto.type = 'series.__base__';
        proto.seriesIndex = 0;
        proto.ignoreStyleOnData = false;
        proto.hasSymbolVisual = false;
        proto.defaultSymbol = 'circle';
        // Make sure the values can be accessed!
        proto.visualStyleAccessPath = 'itemStyle';
        proto.visualDrawType = 'fill';
    })();


    init(option: Opt, parentModel: Model, ecModel: GlobalModel) {

        this.seriesIndex = this.componentIndex;

        this.dataTask = createTask<SeriesTaskContext>({
            count: dataTaskCount,
            reset: dataTaskReset
        });
        this.dataTask.context = {model: this};

        this.mergeDefaultAndTheme(option, ecModel);

        const sourceManager = inner(this).sourceManager = new SourceManager(this);
        sourceManager.prepareSource();

        const data = this.getInitialData(option, ecModel);
        wrapData(data, this);
        this.dataTask.context.data = data;

        if (__DEV__) {
            zrUtil.assert(data, 'getInitialData returned invalid data.');
        }

        inner(this).dataBeforeProcessed = data;

        // If we reverse the order (make data firstly, and then make
        // dataBeforeProcessed by cloneShallow), cloneShallow will
        // cause data.graph.data !== data when using
        // module:echarts/data/Graph or module:echarts/data/Tree.
        // See module:echarts/data/helper/linkSeriesData

        // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model
        // init or merge stage, because the data can be restored. So we do not `restoreData`
        // and `setData` here, which forbids calling `seriesModel.getData()` in this stage.
        // Call `seriesModel.getRawData()` instead.
        // this.restoreData();

        autoSeriesName(this);

        this._initSelectedMapFromData(data);
    }

    /**
     * Util for merge default and theme to option
     */
    mergeDefaultAndTheme(option: Opt, ecModel: GlobalModel): void {
        const layoutMode = fetchLayoutMode(this);
        const inputPositionParams = layoutMode
            ? getLayoutParams(option as BoxLayoutOptionMixin) : {};

        // Backward compat: using subType on theme.
        // But if name duplicate between series subType
        // (for example: parallel) add component mainType,
        // add suffix 'Series'.
        let themeSubType = this.subType;
        if ((ComponentModel as ComponentModelConstructor).hasClass(themeSubType)) {
            themeSubType += 'Series';
        }
        zrUtil.merge(
            option,
            ecModel.getTheme().get(this.subType)
        );
        zrUtil.merge(option, this.getDefaultOption());

        // Default label emphasis `show`
        modelUtil.defaultEmphasis(option, 'label', ['show']);

        this.fillDataTextStyle(option.data as ArrayLike<any>);

        if (layoutMode) {
            mergeLayoutParam(option as BoxLayoutOptionMixin, inputPositionParams, layoutMode);
        }
    }

    mergeOption(newSeriesOption: Opt, ecModel: GlobalModel) {
        // this.settingTask.dirty();

        newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true);
        this.fillDataTextStyle(newSeriesOption.data as ArrayLike<any>);

        const layoutMode = fetchLayoutMode(this);
        if (layoutMode) {
            mergeLayoutParam(
                this.option as BoxLayoutOptionMixin,
                newSeriesOption as BoxLayoutOptionMixin,
                layoutMode
            );
        }

        const sourceManager = inner(this).sourceManager;
        sourceManager.dirty();
        sourceManager.prepareSource();

        const data = this.getInitialData(newSeriesOption, ecModel);
        wrapData(data, this);
        this.dataTask.dirty();
        this.dataTask.context.data = data;

        inner(this).dataBeforeProcessed = data;

        autoSeriesName(this);

        this._initSelectedMapFromData(data);
    }

    fillDataTextStyle(data: ArrayLike<any>): void {
        // Default data label emphasis `show`
        // FIXME Tree structure data ?
        // FIXME Performance ?
        if (data && !zrUtil.isTypedArray(data)) {
            const props = ['show'];
            for (let i = 0; i < data.length; i++) {
                if (data[i] && data[i].label) {
                    modelUtil.defaultEmphasis(data[i], 'label', props);
                }
            }
        }
    }

    /**
     * Init a data structure from data related option in series
     * Must be overridden.
     */
    getInitialData(option: Opt, ecModel: GlobalModel): SeriesData {
        return;
    }

    /**
     * Append data to list
     */
    appendData(params: {data: ArrayLike<any>}): void {
        // FIXME ???
        // (1) If data from dataset, forbidden append.
        // (2) support append data of dataset.
        const data = this.getRawData();
        data.appendData(params.data);
    }

    /**
     * Consider some method like `filter`, `map` need make new data,
     * We should make sure that `seriesModel.getData()` get correct
     * data in the stream procedure. So we fetch data from upstream
     * each time `task.perform` called.
     */
    getData(dataType?: SeriesDataType): SeriesData<this> {
        const task = getCurrentTask(this);
        if (task) {
            const data = task.context.data;
            return (dataType == null ? data : data.getLinkedData(dataType)) as SeriesData<this>;
        }
        else {
            // When series is not alive (that may happen when click toolbox
            // restore or setOption with not merge mode), series data may
            // be still need to judge animation or something when graphic
            // elements want to know whether fade out.
            return inner(this).data as SeriesData<this>;
        }
    }

    getAllData(): ({
        data: SeriesData,
        type?: SeriesDataType
    })[] {
        const mainData = this.getData();
        return (mainData && mainData.getLinkedDataAll)
            ? mainData.getLinkedDataAll()
            : [{ data: mainData }];
    }

    setData(data: SeriesData): void {
        const task = getCurrentTask(this);
        if (task) {
            const context = task.context;
            // Consider case: filter, data sample.
            // FIXME:TS never used, so comment it
            // if (context.data !== data && task.modifyOutputEnd) {
            //     task.setOutputEnd(data.count());
            // }
            context.outputData = data;
            // Caution: setData should update context.data,
            // Because getData may be called multiply in a
            // single stage and expect to get the data just
            // set. (For example, AxisProxy, x y both call
            // getData and setDate sequentially).
            // So the context.data should be fetched from
            // upstream each time when a stage starts to be
            // performed.
            if (task !== this.dataTask) {
                context.data = data;
            }
        }
        inner(this).data = data;
    }

    getEncode() {
        const encode = (this as Model<SeriesEncodeOptionMixin>).get('encode', true);
        if (encode) {
            return zrUtil.createHashMap<OptionEncodeValue, DimensionName>(encode);
        }
    }

    getSourceManager(): SourceManager {
        return inner(this).sourceManager;
    }

    getSource(): Source {
        return this.getSourceManager().getSource();
    }

    /**
     * Get data before processed
     */
    getRawData(): SeriesData {
        return inner(this).dataBeforeProcessed;
    }

    getColorBy(): ColorBy {
        const colorBy = this.get('colorBy');
        return colorBy || 'series';
    }

    isColorBySeries(): boolean {
        return this.getColorBy() === 'series';
    }

    /**
     * Get base axis if has coordinate system and has axis.
     * By default use coordSys.getBaseAxis();
     * Can be overridden for some chart.
     * @return {type} description
     */
    getBaseAxis(): Axis {
        const coordSys = this.coordinateSystem;
        // @ts-ignore
        return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
    }

    /**
     * Default tooltip formatter
     *
     * @param dataIndex
     * @param multipleSeries
     * @param dataType
     * @param renderMode valid values: 'html'(by default) and 'richText'.
     *        'html' is used for rendering tooltip in extra DOM form, and the result
     *        string is used as DOM HTML content.
     *        'richText' is used for rendering tooltip in rich text form, for those where
     *        DOM operation is not supported.
     * @return formatted tooltip with `html` and `markers`
     *        Notice: The override method can also return string
     */
    formatTooltip(
        dataIndex: number,
        multipleSeries?: boolean,
        dataType?: SeriesDataType
    ): ReturnType<DataFormatMixin['formatTooltip']> {
        return defaultSeriesFormatTooltip({
            series: this,
            dataIndex: dataIndex,
            multipleSeries: multipleSeries
        });
    }

    isAnimationEnabled(): boolean {
        const ecModel = this.ecModel;
        // Disable animation if using echarts in node but not give ssr flag.
        // In ssr mode, renderToString will generate svg with css animation.
        if (env.node && !(ecModel && ecModel.ssr)) {
            return false;
        }
        let animationEnabled = this.getShallow('animation');
        if (animationEnabled) {
            if (this.getData().count() > this.getShallow('animationThreshold')) {
                animationEnabled = false;
            }
        }
        return !!animationEnabled;
    }

    restoreData() {
        this.dataTask.dirty();
    }

    getColorFromPalette(name: string, scope: any, requestColorNum?: number): ZRColor {
        const ecModel = this.ecModel;
        // PENDING
        let color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum);
        if (!color) {
            color = ecModel.getColorFromPalette(name, scope, requestColorNum);
        }
        return color;
    }

    /**
     * Use `data.mapDimensionsAll(coordDim)` instead.
     * @deprecated
     */
    coordDimToDataDim(coordDim: DimensionName): DimensionName[] {
        return this.getRawData().mapDimensionsAll(coordDim);
    }

    /**
     * Get progressive rendering count each step
     */
    getProgressive(): number | false {
        return this.get('progressive');
    }

    /**
     * Get progressive rendering count each step
     */
    getProgressiveThreshold(): number {
        return this.get('progressiveThreshold');
    }

    // PENGING If selectedMode is null ?
    select(innerDataIndices: number[], dataType?: SeriesDataType): void {
        this._innerSelect(this.getData(dataType), innerDataIndices);
    }

    unselect(innerDataIndices: number[], dataType?: SeriesDataType): void {
        const selectedMap = this.option.selectedMap;
        if (!selectedMap) {
            return;
        }
        const selectedMode = this.option.selectedMode;

        const data = this.getData(dataType);
        if (selectedMode === 'series' || selectedMap === 'all') {
            this.option.selectedMap = {};
            this._selectedDataIndicesMap = {};
            return;
        }

        for (let i = 0; i < innerDataIndices.length; i++) {
            const dataIndex = innerDataIndices[i];
            const nameOrId = getSelectionKey(data, dataIndex);
            selectedMap[nameOrId] = false;
            this._selectedDataIndicesMap[nameOrId] = -1;
        }
    }

    toggleSelect(innerDataIndices: number[], dataType?: SeriesDataType): void {
        const tmpArr: number[] = [];
        for (let i = 0; i < innerDataIndices.length; i++) {
            tmpArr[0] = innerDataIndices[i];
            this.isSelected(innerDataIndices[i], dataType)
                ? this.unselect(tmpArr, dataType)
                : this.select(tmpArr, dataType);
        }
    }

    getSelectedDataIndices(): number[] {
        if (this.option.selectedMap === 'all') {
            return [].slice.call(this.getData().getIndices());
        }
        const selectedDataIndicesMap = this._selectedDataIndicesMap;
        const nameOrIds = zrUtil.keys(selectedDataIndicesMap);
        const dataIndices = [];
        for (let i = 0; i < nameOrIds.length; i++) {
            const dataIndex = selectedDataIndicesMap[nameOrIds[i]];
            if (dataIndex >= 0) {
                dataIndices.push(dataIndex);
            }
        }
        return dataIndices;
    }

    isSelected(dataIndex: number, dataType?: SeriesDataType): boolean {
        const selectedMap = this.option.selectedMap;
        if (!selectedMap) {
            return false;
        }

        const data = this.getData(dataType);

        return (selectedMap === 'all' || selectedMap[getSelectionKey(data, dataIndex)])
            && !data.getItemModel<StatesOptionMixin<unknown, unknown>>(dataIndex).get(['select', 'disabled']);
    }

    isUniversalTransitionEnabled(): boolean {
        if (this[SERIES_UNIVERSAL_TRANSITION_PROP]) {
            return true;
        }

        const universalTransitionOpt = this.option.universalTransition;
        // Quick reject
        if (!universalTransitionOpt) {
            return false;
        }

        if (universalTransitionOpt === true) {
            return true;
        }

        // Can be simply 'universalTransition: true'
        return universalTransitionOpt && universalTransitionOpt.enabled;
    }

    private _innerSelect(data: SeriesData, innerDataIndices: number[]) {
        const option = this.option;
        const selectedMode = option.selectedMode;
        const len = innerDataIndices.length;
        if (!selectedMode || !len) {
            return;
        }

        if (selectedMode === 'series') {
            option.selectedMap = 'all';
        }
        else if (selectedMode === 'multiple') {
            if (!zrUtil.isObject(option.selectedMap)) {
                option.selectedMap = {};
            }
            const selectedMap = option.selectedMap;
            for (let i = 0; i < len; i++) {
                const dataIndex = innerDataIndices[i];
                // TODO different types of data share same object.
                const nameOrId = getSelectionKey(data, dataIndex);
                selectedMap[nameOrId] = true;
                this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex);
            }
        }
        else if (selectedMode === 'single' || selectedMode === true) {
            const lastDataIndex = innerDataIndices[len - 1];
            const nameOrId = getSelectionKey(data, lastDataIndex);
            option.selectedMap = {
                [nameOrId]: true
            };
            this._selectedDataIndicesMap = {
                [nameOrId]: data.getRawIndex(lastDataIndex)
            };
        }
    }

    private _initSelectedMapFromData(data: SeriesData) {
        // Ignore select info in data if selectedMap exists.
        // NOTE It's only for legacy usage. edge data is not supported.
        if (this.option.selectedMap) {
            return;
        }

        const dataIndices: number[] = [];
        if (data.hasItemOption) {
            data.each(function (idx) {
                const rawItem = data.getRawDataItem(idx);
                if (rawItem && (rawItem as OptionDataItemObject<unknown>).selected) {
                    dataIndices.push(idx);
                }
            });
        }

        if (dataIndices.length > 0) {
            this._innerSelect(data, dataIndices);
        }
    }

    // /**
    //  * @see {module:echarts/stream/Scheduler}
    //  */
    // abstract pipeTask: null

    static registerClass(clz: Constructor): Constructor {
        return ComponentModel.registerClass(clz);
    }
}

interface SeriesModel<Opt extends SeriesOption = SeriesOption>
    extends DataFormatMixin, PaletteMixin<Opt>, DataHost {

    // methods that can be implemented optionally to provide to components
    /**
     * Get dimension to render shadow in dataZoom component
     */
    getShadowDim?(): string
}
zrUtil.mixin(SeriesModel, DataFormatMixin);
zrUtil.mixin(SeriesModel, PaletteMixin);

export type SeriesModelConstructor = typeof SeriesModel & ExtendableConstructor;
mountExtend(SeriesModel, ComponentModel as SeriesModelConstructor);


/**
 * MUST be called after `prepareSource` called
 * Here we need to make auto series, especially for auto legend. But we
 * do not modify series.name in option to avoid side effects.
 */
function autoSeriesName(seriesModel: SeriesModel): void {
    // User specified name has higher priority, otherwise it may cause
    // series can not be queried unexpectedly.
    const name = seriesModel.name;
    if (!modelUtil.isNameSpecified(seriesModel)) {
        seriesModel.name = getSeriesAutoName(seriesModel) || name;
    }
}

function getSeriesAutoName(seriesModel: SeriesModel): string {
    const data = seriesModel.getRawData();
    const dataDims = data.mapDimensionsAll('seriesName');
    const nameArr: string[] = [];
    zrUtil.each(dataDims, function (dataDim) {
        const dimInfo = data.getDimensionInfo(dataDim);
        dimInfo.displayName && nameArr.push(dimInfo.displayName);
    });
    return nameArr.join(' ');
}

function dataTaskCount(context: SeriesTaskContext): number {
    return context.model.getRawData().count();
}

function dataTaskReset(context: SeriesTaskContext) {
    const seriesModel = context.model;
    seriesModel.setData(seriesModel.getRawData().cloneShallow());
    return dataTaskProgress;
}

function dataTaskProgress(param: StageHandlerProgressParams, context: SeriesTaskContext): void {
    // Avoid repead cloneShallow when data just created in reset.
    if (context.outputData && param.end > context.outputData.count()) {
        context.model.getRawData().cloneShallow(context.outputData);
    }
}

// TODO refactor
function wrapData(data: SeriesData, seriesModel: SeriesModel): void {
    zrUtil.each(zrUtil.concatArray(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) {
        data.wrapMethod(methodName as any, zrUtil.curry(onDataChange, seriesModel));
    });
}

function onDataChange(this: SeriesData, seriesModel: SeriesModel, newList: SeriesData): SeriesData {
    const task = getCurrentTask(seriesModel);
    if (task) {
        // Consider case: filter, selectRange
        task.setOutputEnd((newList || this).count());
    }
    return newList;
}

function getCurrentTask(seriesModel: SeriesModel): GeneralTask {
    const scheduler = (seriesModel.ecModel || {}).scheduler;
    const pipeline = scheduler && scheduler.getPipeline(seriesModel.uid);

    if (pipeline) {
        // When pipline finished, the currrentTask keep the last
        // task (renderTask).
        let task = pipeline.currentTask;
        if (task) {
            const agentStubMap = (task as OverallTask).agentStubMap;
            if (agentStubMap) {
                task = agentStubMap.get(seriesModel.uid);
            }
        }
        return task;
    }
}


export default SeriesModel;
