/*
* 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.
*/

const {waitTime} = require('./util');

module.exports = class Timeline {

    constructor(page) {
        this._page = page;

        this._timer = 0;
        this._current = 0;

        this._ops = [];
        this._currentOpIndex = 0;

        this._client;

        this._isLastOpMousewheel = false;
    }

    _reset() {
        this._currentOpIndex = 0;
        this._current = Date.now();
        this._elapsedTime = 0;
        this._isLastOpMousewheel = false;
    }


    async runAction(action, takeScreenshot, playbackSpeed) {
        if (!this._client) {
            this._client = await this._page.target().createCDPSession();
        }

        this.stop();

        playbackSpeed = playbackSpeed || 1;

        if (!action.ops.length) {
            return;
        }

        this._ops = action.ops.slice().sort((a, b) => {
            return a.time - b.time;
        });
        let firstOp = this._ops[0];
        this._ops.forEach(op => {
            op.time -= firstOp.time;
        });

        this._reset();

        let self = this;

        return new Promise(resolve => {
            async function tick() {
                let current = Date.now();
                let dTime = current - self._current;
                self._elapsedTime += dTime * playbackSpeed;
                self._current = current;

                await self._update(takeScreenshot, playbackSpeed);
                if (self._currentOpIndex >= self._ops.length) {
                    // Finished
                    resolve();
                }
                else {
                    self._timer = setTimeout(tick, 16);
                }
            }
            tick();
        });
    }


    stop() {
        if (this._timer) {
            clearTimeout(this._timer);
            this._timer = 0;
        }
    }

    async _update(takeScreenshot, playbackSpeed) {
        let op = this._ops[this._currentOpIndex];

        if (op.time > this._elapsedTime) {
            // Not yet.
            return;
        }

        let page = this._page;
        let takenScreenshot = false;
        switch (op.type) {
            case 'mousedown':
                await page.mouse.move(op.x, op.y);
                await page.mouse.down();
                break;
            case 'mouseup':
                await page.mouse.move(op.x, op.y);
                await page.mouse.up();
                break;
            case 'mousemove':
                await page.mouse.move(op.x, op.y);
                break;
            case 'mousewheel':
                await page.evaluate((x, y, deltaX, deltaY) => {
                    let element = document.elementFromPoint(x, y);
                    // Here dispatch mousewheel event because echarts used it.
                    // TODO Consider upgrade?
                    let event = new WheelEvent('mousewheel', {
                        // PENDING
                        // Needs inverse delta?
                        deltaY,
                        clientX: x, clientY: y,
                        // Needs bubble to parent container
                        bubbles: true
                    });

                    element.dispatchEvent(event);
                }, op.x, op.y, op.deltaX || 0, op.deltaY);
                this._isLastOpMousewheel = true;
                // console.log('mousewheel', op.x, op.y, op.deltaX, op.deltaY);
                // await this._client.send('Input.dispatchMouseEvent', {
                //     type: 'mouseWheel',
                //     x: op.x,
                //     y: op.y,
                //     deltaX: op.deltaX,
                //     deltaY: op.deltaY
                // });
                break;
            case 'screenshot':
                await takeScreenshot();
                takenScreenshot = true;
                break;
            case 'valuechange':
                if (op.target === 'select') {
                    await page.select(op.selector, op.value);
                }
                break;
        }

        this._currentOpIndex++;

        // If next op is an auto screenshot
        let nextOp = this._ops[this._currentOpIndex];
        if (nextOp && nextOp.type === 'screenshot-auto') {
            let delay = nextOp.delay == null ? 400 : nextOp.delay;
            // TODO Configuration time
            await waitTime(delay / playbackSpeed);
            await takeScreenshot();
            takenScreenshot = true;
            this._currentOpIndex++;
        }

        if (this._isLastOpMousewheel && op.type !== 'mousewheel') {
            // Only take screenshot after mousewheel finished
            if (!takenScreenshot) {
                takeScreenshot();
            }
            this._isLastOpMousewheel = false;
        }
    }
};