"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 });
exports.Pin = void 0;
const EventEmitter_1 = require("./EventEmitter");
const primitive_1 = require("./spec/primitive");
class Pin extends EventEmitter_1.EventEmitter_ {
    constructor({ data, constant, ignored, ref } = {}) {
        super();
        this._constant = false;
        this._ignored = false;
        this._ref = false;
        this._invalid = false;
        this._idle = true;
        this._register = undefined;
        if (data !== undefined) {
            this._idle = false;
        }
        this._register = data;
        this._constant = constant || false;
        this._ignored = ignored || false;
        this._ref = ref || false;
    }
    take() {
        const data = this._register;
        if (this._register !== undefined) {
            this._register = undefined;
            this.emit('drop', data);
        }
        this.end();
        return data;
    }
    invalidate() {
        if (this._register !== undefined && !this._invalid) {
            this._invalid = true;
            this._idle = true;
            this.emit('invalid');
        }
    }
    start() {
        if (this._idle) {
            this._idle = false;
            this.emit('start');
        }
    }
    end() {
        if (this._register === undefined && !this._idle) {
            this._idle = true;
            this.emit('end');
        }
    }
    pull() {
        const data = this._register;
        if (data !== undefined) {
            if (this._constant) {
                this.emit('_data', data);
            }
            else {
                this.take();
            }
        }
        return data;
    }
    push(data) {
        this.invalidate();
        this._invalid = false;
        this.start();
        this._register = data;
        this.emit('data', data);
        if (this._ref) {
            //
        }
        else {
            if (this._ignored && !this._constant) {
                this.take();
            }
        }
    }
    peak() {
        return this._register;
    }
    empty() {
        return this._register === undefined;
    }
    active() {
        return !this.empty();
    }
    ignored(value) {
        if (value !== undefined) {
            this._ignored = value;
            if (this._ignored && !this._constant && !this._ref) {
                this.take();
            }
            this.emit('ignored', this._ignored);
        }
        return this._ignored;
    }
    ref(value) {
        if (value !== undefined) {
            this._ref = value;
            this.emit('ref', this._ref);
        }
        return this._ref;
    }
    constant(value) {
        if (value !== undefined) {
            this._constant = value;
        }
        return this._constant;
    }
    invalid() {
        return this._invalid;
    }
    snapshot() {
        return {
            _register: (0, primitive_1.isPrimitive)(this._register) ? this._register : undefined,
            _invalid: this._invalid,
            _constant: this._constant,
            _ignored: this._ignored,
            _idle: this._idle,
        };
    }
    restore(state) {
        const { _register, _invalid, _constant, _ignored, _idle } = state;
        this._register = _register;
        this._invalid = _invalid;
        this._constant = _constant;
        this._ignored = _ignored;
        this._idle = _idle;
    }
    read() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this._register === undefined) {
                throw new Error('empty');
            }
            return this._register;
        });
    }
    write(data) {
        return __awaiter(this, void 0, void 0, function* () {
            this.push(data);
        });
    }
}
exports.Pin = Pin;
//# sourceMappingURL=Pin.js.map