/*
* 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, isArray} from 'zrender/src/core/util';
import SeriesModel from '../model/Series';
import { Pipeline } from './Scheduler';
import { Payload } from '../util/types';
import List from '../data/List';


export interface TaskContext {
    outputData?: List;
    data?: List;
    payload?: Payload;
    model?: SeriesModel;
};

export type TaskResetCallback<Ctx extends TaskContext> = (
    this: Task<Ctx>, context: Ctx
) => TaskResetCallbackReturn<Ctx>;
export type TaskResetCallbackReturn<Ctx extends TaskContext> =
    void
    | (TaskProgressCallback<Ctx> | TaskProgressCallback<Ctx>[])
    | {
        forceFirstProgress?: boolean
        progress: TaskProgressCallback<Ctx> | TaskProgressCallback<Ctx>[]
    };
export type TaskProgressCallback<Ctx extends TaskContext> = (
    this: Task<Ctx>, params: TaskProgressParams, context: Ctx
) => void;
export type TaskProgressParams = {
    start: number, end: number, count: number, next?: TaskDataIteratorNext
};
export type TaskPlanCallback<Ctx extends TaskContext> = (
    this: Task<Ctx>, context: Ctx
) => TaskPlanCallbackReturn;
export type TaskPlanCallbackReturn = 'reset' | false | null | undefined;
export type TaskCountCallback<Ctx extends TaskContext> = (
    this: Task<Ctx>, context: Ctx
) => number;
export type TaskOnDirtyCallback<Ctx extends TaskContext> = (
    this: Task<Ctx>, context: Ctx
) => void;

type TaskDataIteratorNext = () => number;
type TaskDataIterator = {
    reset: (s: number, e: number, sStep: number, sCount: number) => void,
    next?: TaskDataIteratorNext
};

type TaskDefineParam<Ctx extends TaskContext> = {
    reset?: TaskResetCallback<Ctx>,
    // Returns 'reset' indicate reset immediately
    plan?: TaskPlanCallback<Ctx>,
    // count is used to determine data task.
    count?: TaskCountCallback<Ctx>,
    onDirty?: TaskOnDirtyCallback<Ctx>
};
export type PerformArgs = {
    step?: number,
    skip?: boolean,
    modBy?: number,
    modDataCount?: number
};

/**
 * @param {Object} define
 * @return See the return of `createTask`.
 */
export function createTask<Ctx extends TaskContext>(
    define: TaskDefineParam<Ctx>
): Task<Ctx> {
    return new Task<Ctx>(define);
}

export class Task<Ctx extends TaskContext> {

    private _reset: TaskResetCallback<Ctx>;
    private _plan: TaskPlanCallback<Ctx>;
    private _count: TaskCountCallback<Ctx>;
    private _onDirty: TaskOnDirtyCallback<Ctx>;
    private _progress: TaskProgressCallback<Ctx> | TaskProgressCallback<Ctx>[];
    private _callingProgress: TaskProgressCallback<Ctx>;

    private _dirty: boolean;
    private _modBy: number;
    private _modDataCount: number;
    private _upstream: Task<Ctx>;
    private _downstream: Task<Ctx>;
    private _dueEnd: number;
    private _outputDueEnd: number;
    private _settedOutputEnd: number;
    private _dueIndex: number;
    private _disposed: boolean;

    // Injected in schedular
    __pipeline: Pipeline;
    __idxInPipeline: number;
    __block: boolean;

    // Context must be specified implicitly, to
    // avoid miss update context when model changed.
    context: Ctx;

    constructor(define: TaskDefineParam<Ctx>) {
        define = define || {};

        this._reset = define.reset;
        this._plan = define.plan;
        this._count = define.count;
        this._onDirty = define.onDirty;

        this._dirty = true;
    }

    /**
     * @param step Specified step.
     * @param skip Skip customer perform call.
     * @param modBy Sampling window size.
     * @param modDataCount Sampling count.
     * @return whether unfinished.
     */
    perform(performArgs?: PerformArgs): boolean {
        const upTask = this._upstream;
        const skip = performArgs && performArgs.skip;

        // TODO some refactor.
        // Pull data. Must pull data each time, because context.data
        // may be updated by Series.setData.
        if (this._dirty && upTask) {
            const context = this.context;
            context.data = context.outputData = upTask.context.outputData;
        }

        if (this.__pipeline) {
            this.__pipeline.currentTask = this;
        }

        let planResult;
        if (this._plan && !skip) {
            planResult = this._plan(this.context);
        }

        // Support sharding by mod, which changes the render sequence and makes the rendered graphic
        // elements uniformed distributed when progress, especially when moving or zooming.
        const lastModBy = normalizeModBy(this._modBy);
        const lastModDataCount = this._modDataCount || 0;
        const modBy = normalizeModBy(performArgs && performArgs.modBy);
        const modDataCount = performArgs && performArgs.modDataCount || 0;
        if (lastModBy !== modBy || lastModDataCount !== modDataCount) {
            planResult = 'reset';
        }

        function normalizeModBy(val: number) {
            !(val >= 1) && (val = 1); // jshint ignore:line
            return val;
        }

        let forceFirstProgress;
        if (this._dirty || planResult === 'reset') {
            this._dirty = false;
            forceFirstProgress = this._doReset(skip);
        }

        this._modBy = modBy;
        this._modDataCount = modDataCount;

        const step = performArgs && performArgs.step;

        if (upTask) {
            if (__DEV__) {
                assert(upTask._outputDueEnd != null);
            }
            this._dueEnd = upTask._outputDueEnd;
        }
        // DataTask or overallTask
        else {
            if (__DEV__) {
                assert(!this._progress || this._count);
            }
            this._dueEnd = this._count ? this._count(this.context) : Infinity;
        }

        // Note: Stubs, that its host overall task let it has progress, has progress.
        // If no progress, pass index from upstream to downstream each time plan called.
        if (this._progress) {
            const start = this._dueIndex;
            const end = Math.min(
                step != null ? this._dueIndex + step : Infinity,
                this._dueEnd
            );

            if (!skip && (forceFirstProgress || start < end)) {
                const progress = this._progress;
                if (isArray(progress)) {
                    for (let i = 0; i < progress.length; i++) {
                        this._doProgress(progress[i], start, end, modBy, modDataCount);
                    }
                }
                else {
                    this._doProgress(progress, start, end, modBy, modDataCount);
                }
            }

            this._dueIndex = end;
            // If no `outputDueEnd`, assume that output data and
            // input data is the same, so use `dueIndex` as `outputDueEnd`.
            const outputDueEnd = this._settedOutputEnd != null
                ? this._settedOutputEnd : end;

            if (__DEV__) {
                // ??? Can not rollback.
                assert(outputDueEnd >= this._outputDueEnd);
            }

            this._outputDueEnd = outputDueEnd;
        }
        else {
            // (1) Some overall task has no progress.
            // (2) Stubs, that its host overall task do not let it has progress, has no progress.
            // This should always be performed so it can be passed to downstream.
            this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null
                ? this._settedOutputEnd : this._dueEnd;
        }

        return this.unfinished();
    }

    dirty(): void {
        this._dirty = true;
        this._onDirty && this._onDirty(this.context);
    }

    private _doProgress(
        progress: TaskProgressCallback<Ctx>,
        start: number,
        end: number,
        modBy: number,
        modDataCount: number
    ): void {
        iterator.reset(start, end, modBy, modDataCount);
        this._callingProgress = progress;
        this._callingProgress({
            start: start, end: end, count: end - start, next: iterator.next
        }, this.context);
    }

    private _doReset(skip: boolean): boolean {
        this._dueIndex = this._outputDueEnd = this._dueEnd = 0;
        this._settedOutputEnd = null;

        let progress: TaskResetCallbackReturn<Ctx>;
        let forceFirstProgress: boolean;

        if (!skip && this._reset) {
            progress = this._reset(this.context);
            if (progress && (progress as any).progress) {
                forceFirstProgress = (progress as any).forceFirstProgress;
                progress = (progress as any).progress;
            }
            // To simplify no progress checking, array must has item.
            if (isArray(progress) && !progress.length) {
                progress = null;
            }
        }

        this._progress = progress as TaskProgressCallback<Ctx>;
        this._modBy = this._modDataCount = null;

        const downstream = this._downstream;
        downstream && downstream.dirty();

        return forceFirstProgress;
    }

    unfinished(): boolean {
        return this._progress && this._dueIndex < this._dueEnd;
    }

    /**
     * @param downTask The downstream task.
     * @return The downstream task.
     */
    pipe(downTask: Task<Ctx>): void {
        if (__DEV__) {
            assert(downTask && !downTask._disposed && downTask !== this);
        }

        // If already downstream, do not dirty downTask.
        if (this._downstream !== downTask || this._dirty) {
            this._downstream = downTask;
            downTask._upstream = this;
            downTask.dirty();
        }
    }

    dispose(): void {
        if (this._disposed) {
            return;
        }

        this._upstream && (this._upstream._downstream = null);
        this._downstream && (this._downstream._upstream = null);

        this._dirty = false;
        this._disposed = true;
    }

    getUpstream(): Task<Ctx> {
        return this._upstream;
    }

    getDownstream(): Task<Ctx> {
        return this._downstream;
    }

    setOutputEnd(end: number): void {
        // This only happend in dataTask, dataZoom, map, currently.
        // where dataZoom do not set end each time, but only set
        // when reset. So we should record the setted end, in case
        // that the stub of dataZoom perform again and earse the
        // setted end by upstream.
        this._outputDueEnd = this._settedOutputEnd = end;
    }

    getDueIndex(): number {
        return this._dueIndex;
    }

}

const iterator: TaskDataIterator = (function () {

    let end: number;
    let current: number;
    let modBy: number;
    let modDataCount: number;
    let winCount: number;

    const it: TaskDataIterator = {
        reset: function (s: number, e: number, sStep: number, sCount: number): void {
            current = s;
            end = e;

            modBy = sStep;
            modDataCount = sCount;
            winCount = Math.ceil(modDataCount / modBy);

            it.next = (modBy > 1 && modDataCount > 0) ? modNext : sequentialNext;
        }
    };

    return it;

    function sequentialNext(): number {
        return current < end ? current++ : null;
    }

    function modNext(): number {
        const dataIndex = (current % winCount) * modBy + Math.ceil(current / winCount);
        const result = current >= end
            ? null
            : dataIndex < modDataCount
            ? dataIndex
            // If modDataCount is smaller than data.count() (consider `appendData` case),
            // Use normal linear rendering mode.
            : current;
        current++;
        return result;
    }
})();



///////////////////////////////////////////////////////////
// For stream debug (Should be commented out after used!)
// @usage: printTask(this, 'begin');
// @usage: printTask(this, null, {someExtraProp});
// @usage: Use `__idxInPipeline` as conditional breakpiont.
//
// window.printTask = function (task: any, prefix: string, extra: { [key: string]: unknown }): void {
//     window.ecTaskUID == null && (window.ecTaskUID = 0);
//     task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`);
//     task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`);
//     let props = [];
//     if (task.__pipeline) {
//         let val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`;
//         props.push({text: '__idxInPipeline/total', value: val});
//     } else {
//         let stubCount = 0;
//         task.agentStubMap.each(() => stubCount++);
//         props.push({text: 'idx', value: `overall (stubs: ${stubCount})`});
//     }
//     props.push({text: 'uid', value: task.uidDebug});
//     if (task.__pipeline) {
//         props.push({text: 'pipelineId', value: task.__pipeline.id});
//         task.agent && props.push(
//             {text: 'stubFor', value: task.agent.uidDebug}
//         );
//     }
//     props.push(
//         {text: 'dirty', value: task._dirty},
//         {text: 'dueIndex', value: task._dueIndex},
//         {text: 'dueEnd', value: task._dueEnd},
//         {text: 'outputDueEnd', value: task._outputDueEnd}
//     );
//     if (extra) {
//         Object.keys(extra).forEach(key => {
//             props.push({text: key, value: extra[key]});
//         });
//     }
//     let args = ['color: blue'];
//     let msg = `%c[${prefix || 'T'}] %c` + props.map(item => (
//         args.push('color: green', 'color: red'),
//         `${item.text}: %c${item.value}`
//     )).join('%c, ');
//     console.log.apply(console, [msg].concat(args));
//     // console.log(this);
// };
// window.printPipeline = function (task: any, prefix: string) {
//     const pipeline = task.__pipeline;
//     let currTask = pipeline.head;
//     while (currTask) {
//         window.printTask(currTask, prefix);
//         currTask = currTask._downstream;
//     }
// };
// window.showChain = function (chainHeadTask) {
//     var chain = [];
//     var task = chainHeadTask;
//     while (task) {
//         chain.push({
//             task: task,
//             up: task._upstream,
//             down: task._downstream,
//             idxInPipeline: task.__idxInPipeline
//         });
//         task = task._downstream;
//     }
//     return chain;
// };
// window.findTaskInChain = function (task, chainHeadTask) {
//     let chain = window.showChain(chainHeadTask);
//     let result = [];
//     for (let i = 0; i < chain.length; i++) {
//         let chainItem = chain[i];
//         if (chainItem.task === task) {
//             result.push(i);
//         }
//     }
//     return result;
// };
// window.printChainAEachInChainB = function (chainHeadTaskA, chainHeadTaskB) {
//     let chainA = window.showChain(chainHeadTaskA);
//     for (let i = 0; i < chainA.length; i++) {
//         console.log('chainAIdx:', i, 'inChainB:', window.findTaskInChain(chainA[i].task, chainHeadTaskB));
//     }
// };
