"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const _1 = require("../../../../../Class/$");
const Semifunctional_1 = require("../../../../../Class/Semifunctional");
const gamepad_1 = require("../../../../../client/event/gamepad");
const callAll_1 = require("../../../../../util/call/callAll");
const _ids_1 = require("../../../../_ids");
class _Gamepad extends Semifunctional_1.Semifunctional {
    constructor(system) {
        super({
            fi: ['i'],
            fo: [],
            i: ['done'],
            o: ['state'],
        }, {
            output: {
                state: {
                    ref: true,
                },
            },
        }, system, _ids_1.ID_GAMEPAD);
    }
    f({ i }, done) {
        return __awaiter(this, void 0, void 0, function* () {
            const { api: { input: { gamepad: { getGamepad, addEventListener }, }, }, } = this.__system;
            try {
                const gamepad = getGamepad(i);
                this._gamepad = new gamepad_1.Gamepad_(this.__system, gamepad);
            }
            catch (err) {
                done(undefined, err.message);
                return;
            }
            const onConnect = (event) => {
                const { gamepad } = event;
                const { index } = gamepad;
                if (index === i) {
                    this._gamepad = new gamepad_1.Gamepad_(this.__system, gamepad);
                    pushPad(this._gamepad);
                }
            };
            const onDisconnect = (event) => {
                const { gamepad } = event;
                const { index } = gamepad;
                if (index === i) {
                    this._gamepad = null;
                    pullPad();
                }
            };
            this._unlisten = (0, callAll_1.callAll)([
                addEventListener('gamepadconnected', onConnect),
                addEventListener('gamepaddisconnected', onDisconnect),
                () => {
                    if (this._gamepad) {
                        pullPad();
                    }
                },
            ]);
            const pushPad = (gamepad_) => {
                const pad = new (class Pad extends _1.$ {
                    read() {
                        return __awaiter(this, void 0, void 0, function* () {
                            return gamepad_.state;
                        });
                    }
                    write(data) {
                        return __awaiter(this, void 0, void 0, function* () {
                            throw new Error('cannot write to gamepad state');
                        });
                    }
                })(this.__system);
                this._output.state.push(pad);
            };
            const pullPad = () => {
                this._output.state.pull();
            };
            if (this._gamepad) {
                pushPad(this._gamepad);
            }
        });
    }
    d() {
        this._unlisten();
        this._unlisten = undefined;
    }
    onIterDataInputData(name) {
        // if (name === 'done') {
        this._output.state.pull();
        this._done();
        this._input.done.pull();
        // }
    }
}
exports.default = _Gamepad;
//# sourceMappingURL=index.js.map