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());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
import '@iotize/tap/service/impl/target';
import { GPIOMode } from '@iotize/tap/service/impl/gpio';
import { debug } from './debug';
import { CONFIGURE_MASK, DIRECT_ACCESS_GPIO_FORMAT } from './definitions';
import { GPIO_MAPPING } from './gpio-mapping';
import { encodeMultiAddressInfo, encodeMultiIndexData } from './tap-gpio-converter';
var GPIOManager = /** @class */ (function () {
    function GPIOManager(tap) {
        this.tap = tap;
        this._cache = {};
    }
    GPIOManager.prototype.getPinByIndex = function (index) {
        if (!(index in this._cache)) {
            this._cache[index] = new GPIOPin(this.tap, index);
        }
        return this._cache[index];
    };
    /**
     * TODO min api version ?
     * @param options
     */
    GPIOManager.prototype.readValues = function (indexs) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this._readMuliple(indexs || GPIO_MAPPING.map(function (pin) { return pin.index; }), false)];
            });
        });
    };
    /**
     * TODO min api version ?
     * @param options
     */
    GPIOManager.prototype.readConfig = function (indexs) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this._readMuliple(indexs || GPIO_MAPPING.map(function (pin) { return pin.index; }), true)];
            });
        });
    };
    GPIOManager.prototype._readMuliple = function (indexs, config) {
        return __awaiter(this, void 0, void 0, function () {
            var memoryInfo, results, formwattedResult;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        memoryInfo = encodeMultiAddressInfo(indexs, config);
                        return [4 /*yield*/, this.tap.service.target.readAddress(memoryInfo)];
                    case 1:
                        results = (_a.sent()).body();
                        formwattedResult = Array.from(results).map(function (v, index) {
                            return {
                                index: memoryInfo.address + index,
                                value: (config ? v : !!v)
                            };
                        });
                        return [2 /*return*/, formwattedResult];
                }
            });
        });
    };
    GPIOManager.prototype.writeValues = function (indexValues) {
        return __awaiter(this, void 0, void 0, function () {
            var indexs, memoryInfo, encodedData;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (typeof indexValues === 'boolean') {
                            indexValues = GPIO_MAPPING.map(function (pin) { return ({
                                index: pin.index,
                                value: indexValues
                            }); });
                        }
                        indexs = indexValues.map(function (info) { return info.index; });
                        memoryInfo = encodeMultiAddressInfo(indexs);
                        encodedData = encodeMultiIndexData(indexValues);
                        return [4 /*yield*/, this.tap.service.target.writeAddress({
                                data: encodedData,
                                info: memoryInfo
                            })];
                    case 1:
                        (_a.sent()).successful();
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * TODO min api version ?
     * @param options
     */
    GPIOManager.prototype.writeConfig = function (indexValues) {
        return __awaiter(this, void 0, void 0, function () {
            var indexs, memoryInfo, encodedData;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (typeof indexValues === 'number') {
                            indexValues = GPIO_MAPPING.map(function (pin) { return ({
                                index: pin.index,
                                value: indexValues
                            }); });
                        }
                        indexs = indexValues.map(function (info) { return info.index; });
                        memoryInfo = encodeMultiAddressInfo(indexs, true);
                        encodedData = encodeMultiIndexData(indexValues);
                        return [4 /*yield*/, this.tap.service.target.writeAddress({
                                data: encodedData,
                                info: memoryInfo
                            })];
                    case 1:
                        (_a.sent()).successful();
                        return [2 /*return*/];
                }
            });
        });
    };
    return GPIOManager;
}());
export { GPIOManager };
export function pinIndexToConfigureAddress(index) {
    return (CONFIGURE_MASK | index) >>> 0;
}
var GPIOPin = /** @class */ (function () {
    function GPIOPin(tap, index) {
        this.tap = tap;
        this.index = index;
    }
    GPIOPin.prototype.readConfig = function () {
        return __awaiter(this, void 0, void 0, function () {
            var body;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        debug("Read config for pin=" + this.index + "...");
                        return [4 /*yield*/, this.tap.service.target.readAddress({
                                address: pinIndexToConfigureAddress(this.index),
                                format: DIRECT_ACCESS_GPIO_FORMAT,
                                length: 1
                            })];
                    case 1:
                        body = (_a.sent()).body();
                        // TODO check body.length >= 1
                        return [2 /*return*/, body[0]];
                }
            });
        });
    };
    GPIOPin.prototype.writeConfig = function (options) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(options.mode in GPIOMode)) {
                            throw new Error("Unknown mode GPIO mode " + options.mode);
                        }
                        debug("writeConfig on pin=" + this.index, GPIOMode[options.mode]);
                        return [4 /*yield*/, this.tap.service.target.writeAddress({
                                data: Uint8Array.from([options.mode]),
                                info: {
                                    address: pinIndexToConfigureAddress(this.index),
                                    format: DIRECT_ACCESS_GPIO_FORMAT,
                                    length: 1
                                }
                            })];
                    case 1:
                        (_a.sent()).successful();
                        return [2 /*return*/];
                }
            });
        });
    };
    GPIOPin.prototype.readValue = function () {
        return __awaiter(this, void 0, void 0, function () {
            var rawBody, value;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.tap.service.target.readAddress({
                            address: this.index,
                            format: DIRECT_ACCESS_GPIO_FORMAT,
                            length: 1
                        })];
                    case 1:
                        rawBody = (_a.sent()).body();
                        if (rawBody.length !== 1) {
                            throw new Error("Unexpected Tap response for read Address. Should be 1 byte but received " + rawBody.length + " bytes");
                        }
                        value = !!rawBody[0];
                        debug("Read value for pin=" + this.index + " ==> " + value);
                        return [2 /*return*/, value];
                }
            });
        });
    };
    GPIOPin.prototype.writeValue = function (value) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        debug("Write value on pin=" + this.index + "; " + value);
                        return [4 /*yield*/, this.tap.service.target.writeAddress({
                                data: value ? Uint8Array.from([1]) : Uint8Array.from([0]),
                                info: {
                                    address: this.index,
                                    format: DIRECT_ACCESS_GPIO_FORMAT,
                                    length: 1
                                }
                            })];
                    case 1: return [2 /*return*/, (_a.sent()).body()];
                }
            });
        });
    };
    return GPIOPin;
}());
export { GPIOPin };
//# sourceMappingURL=data:application/json;base64, 