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());
    });
};
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';
export class GPIOManager {
    constructor(tap) {
        this.tap = tap;
        this._cache = {};
    }
    getPinByIndex(index) {
        if (!(index in this._cache)) {
            this._cache[index] = new GPIOPin(this.tap, index);
        }
        return this._cache[index];
    }
    /**
     * TODO min api version ?
     * @param options
     */
    readValues(indexs) {
        return __awaiter(this, void 0, void 0, function* () {
            return this._readMuliple(indexs || GPIO_MAPPING.map(pin => pin.index), false);
        });
    }
    /**
     * TODO min api version ?
     * @param options
     */
    readConfig(indexs) {
        return __awaiter(this, void 0, void 0, function* () {
            return this._readMuliple(indexs || GPIO_MAPPING.map(pin => pin.index), true);
        });
    }
    _readMuliple(indexs, config) {
        return __awaiter(this, void 0, void 0, function* () {
            const memoryInfo = encodeMultiAddressInfo(indexs, config);
            const results = (yield this.tap.service.target.readAddress(memoryInfo)).body();
            const formwattedResult = Array.from(results).map((v, index) => {
                return {
                    index: memoryInfo.address + index,
                    value: (config ? v : !!v)
                };
            });
            return formwattedResult;
        });
    }
    writeValues(indexValues) {
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof indexValues === 'boolean') {
                indexValues = GPIO_MAPPING.map(pin => ({
                    index: pin.index,
                    value: indexValues
                }));
            }
            const indexs = indexValues.map(info => info.index);
            const memoryInfo = encodeMultiAddressInfo(indexs);
            const encodedData = encodeMultiIndexData(indexValues);
            (yield this.tap.service.target.writeAddress({
                data: encodedData,
                info: memoryInfo
            })).successful();
        });
    }
    /**
     * TODO min api version ?
     * @param options
     */
    writeConfig(indexValues) {
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof indexValues === 'number') {
                indexValues = GPIO_MAPPING.map(pin => ({
                    index: pin.index,
                    value: indexValues
                }));
            }
            const indexs = indexValues.map(info => info.index);
            const memoryInfo = encodeMultiAddressInfo(indexs, true);
            const encodedData = encodeMultiIndexData(indexValues);
            (yield this.tap.service.target.writeAddress({
                data: encodedData,
                info: memoryInfo
            })).successful();
        });
    }
}
export function pinIndexToConfigureAddress(index) {
    return (CONFIGURE_MASK | index) >>> 0;
}
export class GPIOPin {
    constructor(tap, index) {
        this.tap = tap;
        this.index = index;
    }
    readConfig() {
        return __awaiter(this, void 0, void 0, function* () {
            debug(`Read config for pin=${this.index}...`);
            const body = (yield this.tap.service.target.readAddress({
                address: pinIndexToConfigureAddress(this.index),
                format: DIRECT_ACCESS_GPIO_FORMAT,
                length: 1
            })).body();
            // TODO check body.length >= 1
            return body[0];
        });
    }
    writeConfig(options) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!(options.mode in GPIOMode)) {
                throw new Error(`Unknown mode GPIO mode ${options.mode}`);
            }
            debug(`writeConfig on pin=${this.index}`, GPIOMode[options.mode]);
            (yield this.tap.service.target.writeAddress({
                data: Uint8Array.from([options.mode]),
                info: {
                    address: pinIndexToConfigureAddress(this.index),
                    format: DIRECT_ACCESS_GPIO_FORMAT,
                    length: 1
                }
            })).successful();
        });
    }
    readValue() {
        return __awaiter(this, void 0, void 0, function* () {
            const rawBody = (yield this.tap.service.target.readAddress({
                address: this.index,
                format: DIRECT_ACCESS_GPIO_FORMAT,
                length: 1
            })).body();
            if (rawBody.length !== 1) {
                throw new Error(`Unexpected Tap response for read Address. Should be 1 byte but received ${rawBody.length} bytes`);
            }
            const value = !!rawBody[0];
            debug(`Read value for pin=${this.index} ==> ${value}`);
            return value;
        });
    }
    writeValue(value) {
        return __awaiter(this, void 0, void 0, function* () {
            debug(`Write value on pin=${this.index}; ${value}`);
            return (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
                }
            })).body();
        });
    }
}
//# sourceMappingURL=data:application/json;base64, 