/*
 * Copyright (C) 2016-2020 Kano Computing Ltd.
 * License: http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
 */
import { AppModule } from '../../app-modules/app-module.js';
import { EventEmitter } from '@kano/common/index.js';
import { transformLegacy } from './legacy.js';
const COLLISION_DETECTION_RATE = 25;
export class ApplicationModule extends AppModule {
    constructor(output) {
        super(output);
        this._onDidStart = new EventEmitter();
        this._onDidPartCollision = new EventEmitter();
        this._justRestarted = false;
        this.userSubscriptions = [];
        this.collisionInterval = null;
        this.watchedCollisions = [];
        this.addMethod('onStart', '_onStart');
        this.addMethod('onPartCollision', '_onPartCollision');
        this.addMethod('restart', '_restart');
        this.addLifecycleStep('stop', '_reset');
        this.addLifecycleStep('afterRun', '_start');
    }
    static transformLegacy(app) {
        transformLegacy(app);
    }
    static get id() { return 'app'; }
    _onStart(callback) {
        this._onDidStart.event(callback, null, this.userSubscriptions);
    }
    _onPartCollision(a, b, callback) {
        this._setupCollisionDetection();
        this.watchedCollisions.push({ a, b, callback });
    }
    _setupCollisionDetection() {
        this._stopCollisionDetection();
        this.collisionInterval = window.setInterval(() => {
            const parts = this.output.parts.getParts();
            const partsMap = new Map();
            parts.forEach((a) => {
                if (!a.id) {
                    return;
                }
                partsMap.set(a.id, a);
            });
            this.watchedCollisions.forEach((watcher) => {
                const a = partsMap.get(watcher.a);
                const b = partsMap.get(watcher.b);
                if (!a || !b || a === b) {
                    return;
                }
                const aRect = a.getCollidableRect();
                const bRect = b.getCollidableRect();
                if (aRect.x < bRect.x + bRect.width &&
                    aRect.x + aRect.width > bRect.x &&
                    aRect.y < bRect.y + bRect.height &&
                    aRect.y + aRect.height > bRect.y) {
                    watcher.callback();
                    this._onDidPartCollision.fire({ a, b });
                }
            });
        }, COLLISION_DETECTION_RATE);
    }
    _stopCollisionDetection() {
        if (this.collisionInterval) {
            clearInterval(this.collisionInterval);
        }
    }
    _start() {
        this._onDidStart.fire();
    }
    _reset() {
        this._stopCollisionDetection();
        this.watchedCollisions = [];
        this.userSubscriptions.forEach(d => d.dispose());
        this.userSubscriptions.length = 0;
    }
    _restart() {
        if (this._justRestarted) {
            return;
        }
        this._justRestarted = true;
        this.output.restart();
        setTimeout(() => {
            this._justRestarted = false;
        });
    }
}
export default ApplicationModule;
//# sourceMappingURL=app.js.map