export class SerenaTiltOnlyWoodBlinds {
    platform;
    accessory;
    bridge;
    service;
    device;
    constructor(platform, accessory, bridge) {
        this.platform = platform;
        this.accessory = accessory;
        this.bridge = bridge;
        this.device = accessory.context.device;
        this.accessory
            .getService(this.platform.api.hap.Service.AccessoryInformation)
            .setCharacteristic(this.platform.api.hap.Characteristic.Manufacturer, 'Lutron Electronics Co., Inc')
            .setCharacteristic(this.platform.api.hap.Characteristic.Model, this.device.ModelNumber)
            .setCharacteristic(this.platform.api.hap.Characteristic.Name, this.device.FullyQualifiedName.join(' '))
            .setCharacteristic(this.platform.api.hap.Characteristic.ConfiguredName, this.device.FullyQualifiedName.join(' '))
            .setCharacteristic(this.platform.api.hap.Characteristic.SerialNumber, this.device.SerialNumber.toString());
        this.service
            = this.accessory.getService(this.platform.api.hap.Service.WindowCovering)
                || this.accessory.addService(this.platform.api.hap.Service.WindowCovering);
        this.service.setCharacteristic(this.platform.api.hap.Characteristic.Name, this.device.FullyQualifiedName.join(' '));
        // create handlers for required characteristics
        const getter = (cb) => {
            this.handleCurrentPositionGet().then((pos) => {
                cb(null, pos);
            }, (e) => {
                cb(e);
            });
        };
        const setter = (pos, cb) => {
            this.handleTargetPositionSet(pos).then(() => {
                cb(null, pos);
            }, (e) => {
                cb(e);
            });
        };
        this.service
            .getCharacteristic(this.platform.api.hap.Characteristic.CurrentPosition)
            .on("get" /* this.platform.api.hap.CharacteristicEventTypes.GET */, getter);
        this.service
            .getCharacteristic(this.platform.api.hap.Characteristic.TargetPosition)
            .on("get" /* this.platform.api.hap.CharacteristicEventTypes.GET */, getter)
            .on("set" /* this.platform.api.hap.CharacteristicEventTypes.SET */, setter);
        this.service
            .getCharacteristic(this.platform.api.hap.Characteristic.PositionState)
            .on("get" /* this.platform.api.hap.CharacteristicEventTypes.GET */, this.handlePositionStateGet.bind(this));
        this.platform.on('unsolicited', this.handleUnsolicited.bind(this));
    }
    // `value` can range from 0-100, but n.b. 50 is flat. The Homekit
    // Window Covering's required "Position" characteristic expects 0 to be
    // "fully closed" and 100 to be "fully open". As such, we constrain the
    // tilt angle to [-90,0] degrees by scaling `value` after the fact.
    async handleCurrentPositionGet() {
        this.platform.log.debug('blinds', this.device.FullyQualifiedName.join(' '), 'were asked for current or target position');
        const tilt = await this.bridge.readBlindsTilt(this.device);
        const adj_val = Math.min(100, tilt * 2);
        // Per-poll noise — Homebridge re-reads position frequently. Was info
        // (visible in normal logs); now debug so steady-state operation stays
        // quiet, with global debug bringing it back when troubleshooting.
        this.platform.log.debug('Told Homekit that blinds', this.device.FullyQualifiedName.join(' '), 'are at position', adj_val);
        return adj_val;
    }
    async handleTargetPositionSet(value) {
        const adj_val = Number(value) / 2;
        // Per-command noise — fires every time HomeKit drives the blind. Was
        // info; now debug.
        this.platform.log.debug('Commanded', this.device.FullyQualifiedName.join(' '), 'blinds to (adjusted) value', adj_val);
        await this.bridge.setBlindsTilt(this.device, adj_val);
    }
    handlePositionStateGet(cb) {
        cb(null, this.platform.api.hap.Characteristic.PositionState.STOPPED);
    }
    handleUnsolicited(response) {
        if (response.Header.MessageBodyType === 'OneZoneStatus') {
            if (response.Body?.ZoneStatus?.Zone?.href === this.device.LocalZones[0].href) {
                const adj_val = Math.min(100, response.Body.ZoneStatus.Tilt * 2);
                // Per state-change noise — fires on every physical blind movement.
                // Was info; now debug.
                this.platform.log.debug('Blinds', this.device.FullyQualifiedName.join(' '), 'reported a new position of', adj_val);
                this.accessory
                    .getService(this.platform.api.hap.Service.WindowCovering)
                    .getCharacteristic(this.platform.api.hap.Characteristic.TargetPosition)
                    .updateValue(adj_val);
                this.accessory
                    .getService(this.platform.api.hap.Service.WindowCovering)
                    .getCharacteristic(this.platform.api.hap.Characteristic.CurrentPosition)
                    .updateValue(adj_val);
                const matterApi = this.platform.api.matter;
                if (matterApi && this.accessory?.UUID) {
                    const tiltPercent100ths = Math.max(0, Math.min(10000, Math.round(adj_val * 100)));
                    void matterApi.updateAccessoryState(this.accessory.UUID, 'windowCovering', {
                        currentPositionTiltPercent100ths: tiltPercent100ths,
                        targetPositionTiltPercent100ths: tiltPercent100ths,
                    });
                }
            }
        }
    }
    /**
     * Returns a Matter clusters object for this blind.
     */
    static getMatterClusters() {
        // Tilt-only blinds: Matter §8.3 WindowCovering
        // 0 = open (horizontal), 10000 = closed (vertical) in hundredths of percent
        return {
            windowCovering: {
                currentPositionTiltPercent100ths: 0, // 0=horizontal/open
                targetPositionTiltPercent100ths: 0, // 0=horizontal/open
            },
        };
    }
}
//# sourceMappingURL=SerenaTiltOnlyWoodBlinds.js.map