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

import {each, map, isFunction, createHashMap, noop, HashMap, assert, clone, bind} from 'zrender/src/core/util';
import {
    createTask, Task, TaskContext,
    TaskProgressCallback, TaskProgressParams, TaskPlanCallbackReturn, PerformArgs
} from './task';
import {getUID} from '../util/component';
import GlobalModel from '../model/Global';
import ExtensionAPI from './ExtensionAPI';
import {normalizeToArray} from '../util/model';
import {
    StageHandlerInternal, StageHandlerOverallReset, StageHandler,
    Payload, StageHandlerReset, StageHandlerPlan, StageHandlerProgressExecutor, SeriesLargeOptionMixin, SeriesOption
} from '../util/types';
import { EChartsType } from './echarts';
import SeriesModel from '../model/Series';
import ChartView from '../view/Chart';
import List from '../data/List';
import { ZRenderType } from 'zrender/src/zrender';
import { isMessageChannelTickerAvailable, OnTick, RuntimeStatistic, StatisticDataOnFrame, Ticker } from './ticker';

export type GeneralTask = Task<TaskContext>;
export type SeriesTask = Task<SeriesTaskContext>;
export type OverallTask = Task<OverallTaskContext> & {
    agentStubMap?: HashMap<StubTask>
};
export type StubTask = Task<StubTaskContext> & {
    agent?: OverallTask;
};
export interface ScheduleOption {
    // Experimental features, will not be exposed to users in this way in the final product.
    ticker?: 'frame' | 'messageChannel';
    timeQuota: number;
};
export interface ScheduleOptionInternal extends ScheduleOption {
}

export type Pipeline = {
    id: string
    head: GeneralTask,
    tail: GeneralTask,
    threshold: number,
    progressiveEnabled: boolean,
    blockIndex: number,
    step: number,
    useAutoStep: boolean;
    count: number,
    currentTask?: GeneralTask,
    context?: PipelineContext
};
export type PipelineContext = {
    progressiveRender: boolean,
    modDataCount: number,
    large: boolean
};

type TaskRecord = {
    // key: seriesUID
    seriesTaskMap?: HashMap<SeriesTask>,
    overallTask?: OverallTask
};
type PerformStageTaskOpt = {
    block?: boolean,
    setDirty?: boolean,
    visualType?: StageHandlerInternal['visualType'],
    dirtyMap?: HashMap<any>
};

export interface SeriesTaskContext extends TaskContext {
    model?: SeriesModel;
    data?: List;
    view?: ChartView;
    ecModel?: GlobalModel;
    api?: ExtensionAPI;
    useClearVisual?: boolean;
    plan?: StageHandlerPlan;
    reset?: StageHandlerReset;
    scheduler?: Scheduler;
    payload?: Payload;
    resetDefines?: StageHandlerProgressExecutor[]
}
interface OverallTaskContext extends TaskContext {
    ecModel: GlobalModel;
    api: ExtensionAPI;
    overallReset: StageHandlerOverallReset;
    scheduler: Scheduler;
    payload?: Payload;
}
interface StubTaskContext extends TaskContext {
    model: SeriesModel;
    overallProgress: boolean;
};

const DEFAULT_MESSAGE_CHANNEL_PROGRESSIVE_CHUNK_SIZE = 20;
const AUTO_STEP_FRAME_UPPER_BOUND = 20;
const AUTO_STEP_FRAME_LOWER_BOUND = 15;

class Scheduler {

    readonly ecInstance: EChartsType;
    readonly api: ExtensionAPI;

    // Shared with echarts.js, should only be modified by
    // this file and echarts.js
    unfinished: boolean;

    private _dataProcessorHandlers: StageHandlerInternal[];
    private _visualHandlers: StageHandlerInternal[];
    private _allHandlers: StageHandlerInternal[];

    // key: handlerUID
    private _stageTaskMap: HashMap<TaskRecord> = createHashMap<TaskRecord>();
    // key: pipelineId
    private _pipelineMap: HashMap<Pipeline>;

    private _ticker: Ticker;

    private _scheduleOpt: ScheduleOptionInternal;


    constructor(
        ecInstance: EChartsType,
        api: ExtensionAPI,
        zr: ZRenderType,
        scheduleOpt: ScheduleOption,
        onTick: OnTick,
        dataProcessorHandlers: StageHandlerInternal[],
        visualHandlers: StageHandlerInternal[]
    ) {
        this.ecInstance = ecInstance;
        this.api = api;
        const internalScheduleOpt = this._scheduleOpt = normalizeScheduleOption(scheduleOpt);

        // Fix current processors in case that in some rear cases that
        // processors might be registered after echarts instance created.
        // Register processors incrementally for a echarts instance is
        // not supported by this stream architecture.
        dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice();
        visualHandlers = this._visualHandlers = visualHandlers.slice();
        this._allHandlers = dataProcessorHandlers.concat(visualHandlers);

        this._ticker = new Ticker(zr, internalScheduleOpt, onTick, bind(this._collectStatisticOnFrame, this));
    }

    start() {
        this._ticker.start();
    }

    restoreData(ecModel: GlobalModel, payload: Payload): void {
        // TODO: Only restore needed series and components, but not all components.
        // Currently `restoreData` of all of the series and component will be called.
        // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
        // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
        // and some components like coordinate system, axes, dataZoom, visualMap only
        // need their target series refresh.
        // (1) If we are implementing this feature some day, we should consider these cases:
        // if a data processor depends on a component (e.g., dataZoomProcessor depends
        // on the settings of `dataZoom`), it should be re-performed if the component
        // is modified by `setOption`.
        // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,
        // it should be re-performed when the result array of `getTargetSeries` changed.
        // We use `dependencies` to cover these issues.
        // (3) How to update target series when coordinate system related components modified.

        // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty,
        // and this case all of the tasks will be set as dirty.

        ecModel.restoreData(payload);

        // Theoretically an overall task not only depends on each of its target series, but also
        // depends on all of the series.
        // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks
        // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure
        // that the overall task is set as dirty and to be performed, otherwise it probably cause
        // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it
        // probably cause state chaos (consider `dataZoomProcessor`).
        this._stageTaskMap.each(function (taskRecord) {
            const overallTask = taskRecord.overallTask;
            overallTask && overallTask.dirty();
        });
    }

    // If seriesModel provided, incremental threshold is check by series data.
    getPerformArgs(task: GeneralTask, isBlock?: boolean): {
        step: number, modBy: number, modDataCount: number
    } {
        // For overall task
        if (!task.__pipeline) {
            return;
        }

        const pipeline = this._pipelineMap.get(task.__pipeline.id);
        const pCtx = pipeline.context;
        const incremental = !isBlock
            && pipeline.progressiveEnabled
            && (!pCtx || pCtx.progressiveRender)
            && task.__idxInPipeline > pipeline.blockIndex;

        const step = incremental ? pipeline.step : null;
        const modDataCount = pCtx && pCtx.modDataCount;
        const modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null;

        return {step: step, modBy: modBy, modDataCount: modDataCount};
    }

    getPipeline(pipelineId: string) {
        return this._pipelineMap.get(pipelineId);
    }

    /**
     * Current, progressive rendering starts from visual and layout.
     * Always detect render mode in the same stage, avoiding that incorrect
     * detection caused by data filtering.
     * Caution:
     * `updateStreamModes` use `seriesModel.getData()`.
     */
    updateStreamModes(seriesModel: SeriesModel<SeriesOption & SeriesLargeOptionMixin>, view: ChartView): void {
        const pipeline = this._pipelineMap.get(seriesModel.uid);
        const data = seriesModel.getData();
        const dataLen = data.count();

        // `progressiveRender` means that can render progressively in each
        // animation frame. Note that some types of series do not provide
        // `view.incrementalPrepareRender` but support `chart.appendData`. We
        // use the term `incremental` but not `progressive` to describe the
        // case that `chart.appendData`.
        const progressiveRender = pipeline.progressiveEnabled
            && view.incrementalPrepareRender
            && dataLen >= pipeline.threshold;

        const large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold');

        // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint.
        // see `test/candlestick-large3.html`
        const modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null;

        seriesModel.pipelineContext = pipeline.context = {
            progressiveRender: progressiveRender,
            modDataCount: modDataCount,
            large: large
        };
    }

    restorePipelines(ecModel: GlobalModel): void {
        const scheduler = this;
        const pipelineMap = scheduler._pipelineMap = createHashMap();

        ecModel.eachSeries(seriesModel => {
            const { step, useAutoStep } = this._getSeriesProgressiveChunkSize(seriesModel);
            const pipelineId = seriesModel.uid;

            pipelineMap.set(pipelineId, {
                id: pipelineId,
                head: null,
                tail: null,
                threshold: seriesModel.getProgressiveThreshold(),
                progressiveEnabled: step
                    && !(seriesModel.preventIncremental && seriesModel.preventIncremental()),
                blockIndex: -1,
                step: step,
                useAutoStep: useAutoStep,
                count: 0
            });

            scheduler._pipe(seriesModel, seriesModel.dataTask);
        });
    }

    private _getSeriesProgressiveChunkSize(seriesModel: SeriesModel): {
        step: number,
        useAutoStep: boolean
    } {
        const progressive = seriesModel.getProgressive();
        let step;
        let useAutoStep;

        if (progressive === 'auto') {
            useAutoStep = true;
            step = 5000;
        }
        else if (progressive) {
            step = Math.round(progressive || 700);
        }

        if (progressive && this._scheduleOpt.ticker === 'messageChannel') {
            // PENDING: measure real time cost for chunk size.
            step = DEFAULT_MESSAGE_CHANNEL_PROGRESSIVE_CHUNK_SIZE;
        }

        return { step: step, useAutoStep: useAutoStep };
    }

    private _collectStatisticOnFrame(): StatisticDataOnFrame {
        const pipelineMap = this._pipelineMap;
        let samplePipeline: Pipeline;

        pipelineMap.each(pipeline => {
            if (!samplePipeline) {
                samplePipeline = pipeline;
            }
        });
        return {
            sampleProcessedDataCount: samplePipeline.tail.getDueIndex(),
            samplePipelineStep: samplePipeline.step
        };
    }

    prepareStageTasks(): void {
        const stageTaskMap = this._stageTaskMap;
        const ecModel = this.api.getModel();
        const api = this.api;

        each(this._allHandlers, function (handler) {
            const record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {});

            let errMsg = '';
            if (__DEV__) {
                // Currently do not need to support to sepecify them both.
                errMsg = '"reset" and "overallReset" must not be both specified.';
            }
            assert(!(handler.reset && handler.overallReset), errMsg);

            handler.reset && this._createSeriesStageTask(handler, record, ecModel, api);
            handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api);
        }, this);
    }

    prepareView(view: ChartView, model: SeriesModel, ecModel: GlobalModel, api: ExtensionAPI): void {
        const renderTask = view.renderTask;
        const context = renderTask.context;

        context.model = model;
        context.ecModel = ecModel;
        context.api = api;

        renderTask.__block = !view.incrementalPrepareRender;

        this._pipe(model, renderTask);
    }

    updateStep(): void {
        const scheduler = this;
        const pipelineMap = scheduler._pipelineMap;

        pipelineMap.each(pipeline => {
            const recentFrameTime = this._ticker.getRecentFrameCost() - this._ticker.getRecentIdleCost();
            if (pipeline.useAutoStep && recentFrameTime) {
                const lastStep = pipeline.step;
                if (recentFrameTime > AUTO_STEP_FRAME_UPPER_BOUND) {
                    pipeline.step = 50 + Math.round(lastStep * AUTO_STEP_FRAME_UPPER_BOUND / recentFrameTime);
                }
                else if (recentFrameTime < AUTO_STEP_FRAME_LOWER_BOUND) {
                    pipeline.step = 50 + Math.round(lastStep * AUTO_STEP_FRAME_LOWER_BOUND / recentFrameTime);
                }
            }
        });
    }

    performDataProcessorTasks(ecModel: GlobalModel, payload?: Payload): void {
        // If we do not use `block` here, it should be considered when to update modes.
        this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, {block: true});
    }

    performVisualTasks(
        ecModel: GlobalModel,
        payload?: Payload,
        opt?: PerformStageTaskOpt
    ): void {
        this._performStageTasks(this._visualHandlers, ecModel, payload, opt);
    }

    getRuntimeStatistic(): RuntimeStatistic {
        return this._ticker.getRuntimeStatistic();
    }

    private _performStageTasks(
        stageHandlers: StageHandlerInternal[],
        ecModel: GlobalModel,
        payload: Payload,
        opt?: PerformStageTaskOpt
    ): void {
        opt = opt || {};
        let unfinished: boolean = false;
        const scheduler = this;

        each(stageHandlers, function (stageHandler, idx) {
            if (opt.visualType && opt.visualType !== stageHandler.visualType) {
                return;
            }

            const stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid);
            const seriesTaskMap = stageHandlerRecord.seriesTaskMap;
            const overallTask = stageHandlerRecord.overallTask;

            if (overallTask) {
                let overallNeedDirty;
                const agentStubMap = overallTask.agentStubMap;
                agentStubMap.each(function (stub) {
                    if (needSetDirty(opt, stub)) {
                        stub.dirty();
                        overallNeedDirty = true;
                    }
                });
                overallNeedDirty && overallTask.dirty();
                scheduler.updatePayload(overallTask, payload);
                const performArgs = scheduler.getPerformArgs(overallTask, opt.block);
                // Execute stubs firstly, which may set the overall task dirty,
                // then execute the overall task. And stub will call seriesModel.setData,
                // which ensures that in the overallTask seriesModel.getData() will not
                // return incorrect data.
                agentStubMap.each(function (stub) {
                    stub.perform(performArgs);
                });
                if (overallTask.perform(performArgs)) {
                    unfinished = true;
                }
            }
            else if (seriesTaskMap) {
                seriesTaskMap.each(function (task, pipelineId) {
                    if (needSetDirty(opt, task)) {
                        task.dirty();
                    }
                    const performArgs: PerformArgs = scheduler.getPerformArgs(task, opt.block);
                    // FIXME
                    // if intending to decalare `performRawSeries` in handlers, only
                    // stream-independent (specifically, data item independent) operations can be
                    // performed. Because is a series is filtered, most of the tasks will not
                    // be performed. A stream-dependent operation probably cause wrong biz logic.
                    // Perhaps we should not provide a separate callback for this case instead
                    // of providing the config `performRawSeries`. The stream-dependent operaions
                    // and stream-independent operations should better not be mixed.
                    performArgs.skip = !stageHandler.performRawSeries
                        && ecModel.isSeriesFiltered(task.context.model);
                    scheduler.updatePayload(task, payload);

                    if (task.perform(performArgs)) {
                        unfinished = true;
                    }
                });
            }
        });

        function needSetDirty(opt: PerformStageTaskOpt, task: GeneralTask): boolean {
            return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id));
        }

        this.unfinished = unfinished || this.unfinished;
    }

    performSeriesTasks(ecModel: GlobalModel): void {
        let unfinished: boolean;

        ecModel.eachSeries(function (seriesModel) {
            // Progress to the end for dataInit and dataRestore.
            unfinished = seriesModel.dataTask.perform() || unfinished;
        });

        this.unfinished = unfinished || this.unfinished;
    }

    plan(): void {
        // Travel pipelines, check block.
        this._pipelineMap.each(function (pipeline) {
            let task = pipeline.tail;
            do {
                if (task.__block) {
                    pipeline.blockIndex = task.__idxInPipeline;
                    break;
                }
                task = task.getUpstream();
            }
            while (task);
        });
    }

    updatePayload(
        task: Task<SeriesTaskContext | OverallTaskContext>,
        payload: Payload | 'remain'
    ): void {
        payload !== 'remain' && (task.context.payload = payload);
    }

    private _createSeriesStageTask(
        stageHandler: StageHandlerInternal,
        stageHandlerRecord: TaskRecord,
        ecModel: GlobalModel,
        api: ExtensionAPI
    ): void {
        const scheduler = this;
        const oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap;
        // The count of stages are totally about only several dozen, so
        // do not need to reuse the map.
        const newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap();
        const seriesType = stageHandler.seriesType;
        const getTargetSeries = stageHandler.getTargetSeries;

        // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily,
        // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`,
        // it works but it may cause other irrelevant charts blocked.
        if (stageHandler.createOnAllSeries) {
            ecModel.eachRawSeries(create);
        }
        else if (seriesType) {
            ecModel.eachRawSeriesByType(seriesType, create);
        }
        else if (getTargetSeries) {
            getTargetSeries(ecModel, api).each(create);
        }

        function create(seriesModel: SeriesModel): void {
            const pipelineId = seriesModel.uid;

            // Init tasks for each seriesModel only once.
            // Reuse original task instance.
            const task = newSeriesTaskMap.set(
                pipelineId,
                oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId)
                || createTask<SeriesTaskContext>({
                    plan: seriesTaskPlan,
                    reset: seriesTaskReset,
                    count: seriesTaskCount
                })
            );
            task.context = {
                model: seriesModel,
                ecModel: ecModel,
                api: api,
                // PENDING: `useClearVisual` not used?
                useClearVisual: stageHandler.isVisual && !stageHandler.isLayout,
                plan: stageHandler.plan,
                reset: stageHandler.reset,
                scheduler: scheduler
            };
            scheduler._pipe(seriesModel, task);
        }
    }

    private _createOverallStageTask(
        stageHandler: StageHandlerInternal,
        stageHandlerRecord: TaskRecord,
        ecModel: GlobalModel,
        api: ExtensionAPI
    ): void {
        const scheduler = this;
        const overallTask: OverallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask
            // For overall task, the function only be called on reset stage.
            || createTask<OverallTaskContext>({reset: overallTaskReset});

        overallTask.context = {
            ecModel: ecModel,
            api: api,
            overallReset: stageHandler.overallReset,
            scheduler: scheduler
        };

        const oldAgentStubMap = overallTask.agentStubMap;
        // The count of stages are totally about only several dozen, so
        // do not need to reuse the map.
        const newAgentStubMap = overallTask.agentStubMap = createHashMap<StubTask>();

        const seriesType = stageHandler.seriesType;
        const getTargetSeries = stageHandler.getTargetSeries;
        let overallProgress = true;
        let shouldOverallTaskDirty = false;
        // FIXME:TS never used, so comment it
        // let modifyOutputEnd = stageHandler.modifyOutputEnd;

        // An overall task with seriesType detected or has `getTargetSeries`, we add
        // stub in each pipelines, it will set the overall task dirty when the pipeline
        // progress. Moreover, to avoid call the overall task each frame (too frequent),
        // we set the pipeline block.
        let errMsg = '';
        if (__DEV__) {
            errMsg = '"createOnAllSeries" do not supported for "overallReset", '
                + 'becuase it will block all streams.';
        }
        assert(!stageHandler.createOnAllSeries, errMsg);
        if (seriesType) {
            ecModel.eachRawSeriesByType(seriesType, createStub);
        }
        else if (getTargetSeries) {
            getTargetSeries(ecModel, api).each(createStub);
        }
        // Otherwise, (usually it is legancy case), the overall task will only be
        // executed when upstream dirty. Otherwise the progressive rendering of all
        // pipelines will be disabled unexpectedly. But it still needs stubs to receive
        // dirty info from upsteam.
        else {
            overallProgress = false;
            each(ecModel.getSeries(), createStub);
        }

        function createStub(seriesModel: SeriesModel): void {
            const pipelineId = seriesModel.uid;
            const stub = newAgentStubMap.set(
                pipelineId,
                oldAgentStubMap && oldAgentStubMap.get(pipelineId)
                || (
                    // When the result of `getTargetSeries` changed, the overallTask
                    // should be set as dirty and re-performed.
                    shouldOverallTaskDirty = true,
                    createTask<StubTaskContext>(
                        {reset: stubReset, onDirty: stubOnDirty}
                    )
                )
            );
            stub.context = {
                model: seriesModel,
                overallProgress: overallProgress
                // FIXME:TS never used, so comment it
                // modifyOutputEnd: modifyOutputEnd
            };
            stub.agent = overallTask;
            stub.__block = overallProgress;

            scheduler._pipe(seriesModel, stub);
        }

        if (shouldOverallTaskDirty) {
            overallTask.dirty();
        }
    }

    private _pipe(seriesModel: SeriesModel, task: GeneralTask) {
        const pipelineId = seriesModel.uid;
        const pipeline = this._pipelineMap.get(pipelineId);
        !pipeline.head && (pipeline.head = task);
        pipeline.tail && pipeline.tail.pipe(task);
        pipeline.tail = task;
        task.__idxInPipeline = pipeline.count++;
        task.__pipeline = pipeline;
    }

    static wrapStageHandler(
        stageHandler: StageHandler | StageHandlerOverallReset,
        visualType: StageHandlerInternal['visualType']
    ): StageHandlerInternal {
        if (isFunction(stageHandler)) {
            stageHandler = {
                overallReset: stageHandler,
                seriesType: detectSeriseType(stageHandler)
            } as StageHandlerInternal;
        }

        (stageHandler as StageHandlerInternal).uid = getUID('stageHandler');
        visualType && ((stageHandler as StageHandlerInternal).visualType = visualType);

        return stageHandler as StageHandlerInternal;
    };

}


function overallTaskReset(context: OverallTaskContext): void {
    context.overallReset(
        context.ecModel, context.api, context.payload
    );
}

function stubReset(context: StubTaskContext): TaskProgressCallback<StubTaskContext> {
    return context.overallProgress && stubProgress;
}

function stubProgress(this: StubTask): void {
    this.agent.dirty();
    this.getDownstream().dirty();
}

function stubOnDirty(this: StubTask): void {
    this.agent && this.agent.dirty();
}

function seriesTaskPlan(context: SeriesTaskContext): TaskPlanCallbackReturn {
    return context.plan ? context.plan(
        context.model, context.ecModel, context.api, context.payload
    ) : null;
}

function seriesTaskReset(
    context: SeriesTaskContext
): TaskProgressCallback<SeriesTaskContext> | TaskProgressCallback<SeriesTaskContext>[] {
    if (context.useClearVisual) {
        context.data.clearAllVisual();
    }
    const resetDefines = context.resetDefines = normalizeToArray(
        context.reset(context.model, context.ecModel, context.api, context.payload)
    ) as StageHandlerProgressExecutor[];
    return resetDefines.length > 1
        ? map(resetDefines, function (v, idx) {
            return makeSeriesTaskProgress(idx);
        })
        : singleSeriesTaskProgress;
}

const singleSeriesTaskProgress = makeSeriesTaskProgress(0);

function makeSeriesTaskProgress(resetDefineIdx: number): TaskProgressCallback<SeriesTaskContext> {
    return function (params: TaskProgressParams, context: SeriesTaskContext): void {
        const data = context.data;
        const resetDefine = context.resetDefines[resetDefineIdx];

        if (resetDefine && resetDefine.dataEach) {
            for (let i = params.start; i < params.end; i++) {
                resetDefine.dataEach(data, i);
            }
        }
        else if (resetDefine && resetDefine.progress) {
            resetDefine.progress(params, data);
        }
    };
}

function seriesTaskCount(context: SeriesTaskContext): number {
    return context.data.count();
}



/**
 * Only some legacy stage handlers (usually in echarts extensions) are pure function.
 * To ensure that they can work normally, they should work in block mode, that is,
 * they should not be started util the previous tasks finished. So they cause the
 * progressive rendering disabled. We try to detect the series type, to narrow down
 * the block range to only the series type they concern, but not all series.
 */
function detectSeriseType(legacyFunc: StageHandlerOverallReset): string {
    seriesType = null;
    try {
        // Assume there is no async when calling `eachSeriesByType`.
        legacyFunc(ecModelMock, apiMock);
    }
    catch (e) {
    }
    return seriesType;
}

const ecModelMock: GlobalModel = {} as GlobalModel;
const apiMock: ExtensionAPI = {} as ExtensionAPI;
let seriesType;

mockMethods(ecModelMock, GlobalModel);
mockMethods(apiMock, ExtensionAPI);
ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) {
    seriesType = type;
};
ecModelMock.eachComponent = function (cond: any): void {
    if (cond.mainType === 'series' && cond.subType) {
        seriesType = cond.subType;
    }
};

function mockMethods(target: any, Clz: any): void {
    /* eslint-disable */
    for (let name in Clz.prototype) {
        // Do not use hasOwnProperty
        target[name] = noop;
    }
    /* eslint-enable */
}

function normalizeScheduleOption(scheduleOpt: ScheduleOption): ScheduleOptionInternal {
    const internalOpt = clone(scheduleOpt || {} as ScheduleOption);

    let tickerType = internalOpt.ticker;
    tickerType = internalOpt.ticker = (tickerType === 'messageChannel' && isMessageChannelTickerAvailable())
        ? tickerType : 'frame';

    if (tickerType === 'messageChannel') {
        // By defualt use the empirical value used by react fiber for long time: 5ms
        internalOpt.timeQuota = internalOpt.timeQuota || 5;
    }
    else {
        // In the previous version we use 1ms for long time.
        internalOpt.timeQuota = internalOpt.timeQuota || 1;
    }

    return internalOpt;
}

export default Scheduler;
