// SPDX-License-Identifier: LGPL-3.0-or-later

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* nymea-zigbee
* Zigbee integration module for nymea
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea-zigbee.
*
* nymea-zigbee is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* nymea-zigbee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with nymea-zigbee. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef ZIGBEECLUSTERIASZONE_H
#define ZIGBEECLUSTERIASZONE_H

#include <QObject>

#include "zcl/zigbeecluster.h"
#include "zcl/zigbeeclusterreply.h"

class ZigbeeNode;
class ZigbeeNetwork;
class ZigbeeNodeEndpoint;
class ZigbeeNetworkReply;

class ZigbeeClusterIasZone : public ZigbeeCluster
{
    Q_OBJECT

    friend class ZigbeeNode;
    friend class ZigbeeNetwork;

public:

    enum Attribute {
        // Zone information attribute set
        AttributeZoneState = 0x0000,
        AttributeZoneType = 0x0001,
        AttributeZoneStatus = 0x0002,
        // Zone settings attribute set
        AttributeCieAddress = 0x0010,
        AttributeZoneId = 0x0011,
        AttributeNumberOfZoneSensitivityLevelsSupported = 0x0012,
        AttributeCurrentZoneSensitivityLevel = 0x0013
    };
    Q_ENUM(Attribute)

    enum ZoneState {
        ZoneStateNotEnrolled = 0x00,
        ZoneStateEnrolled = 0x01
    };
    Q_ENUM(ZoneState)

    enum ZoneType {
        ZoneTypeStandardCIE = 0x0000,
        ZoneTypeMotionSensor = 0x000d,
        ZoneTypeContactSwitch = 0x0015,
        ZoneTypeFireSensor = 0x0028,
        ZoneTypeWaterSensor = 0x002a,
        ZoneTypeCarbonMonoxideSensor = 0x002b,
        ZoneTypePersonalEmergencyDevice = 0x002c,
        ZoneTypeVibrationMovementSensor = 0x002d,
        ZoneTypeRemoteControl = 0x010f,
        ZoneTypeKeyFob = 0x0115,
        ZoneTypeKeypad = 0x021d,
        ZoneTypeStandardWarningDevice = 0x0225,
        ZoneTypeGlassBreakSensor = 0x0226,
        ZoneTypeSecurityRepater = 0x0229,
        ZoneTypeInvalidZone = 0xffff
    };
    Q_ENUM(ZoneType)

    enum ZoneStatus {
        ZoneStatusAlarm1 = 0x0001,
        ZoneStatusAlarm2 = 0x0002,
        ZoneStatusTamper = 0x0004,
        ZoneStatusBattery = 0x0008,
        ZoneStatusSupervisionReports = 0x0010,
        ZoneStatusRestoreReports = 0x0020,
        ZoneStatusTrouble = 0x0040,
        ZoneStatusAcMains = 0x0080,
        ZoneStatusTest = 0x0100,
        ZoneStatusBatteryDefect = 0x0200
    };
    Q_FLAG(ZoneStatus)
    Q_DECLARE_FLAGS(ZoneStatusFlags, ZoneStatus)

    enum EnrollResponseCode {
        EnrollResponseCodeSuccess = 0x00,
        EnrollResponseCodeNotSupported = 0x01,
        EnrollResponseCodeNoEnrollPermit = 0x02,
        EnrollResponseCodeToManyZones = 0x03
    };
    Q_ENUM(EnrollResponseCode)

    enum ServerCommand {
        ServerCommandStatusChangedNotification = 0x00, // M
        ServerCommandZoneEnrollRequest = 0x01 // M
    };
    Q_ENUM(ServerCommand)

    enum ClientCommand {
        ClientCommandEnrollResponse = 0x00, // M
        ClientCommandInitNormalOperationMode = 0x01, // O
        ClientCommandInitTestMode = 0x02 // O
    };
    Q_ENUM(ClientCommand)

    explicit ZigbeeClusterIasZone(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);

    ZoneState zoneState() const;
    ZoneType zoneType() const;
    ZoneStatusFlags zoneStatus() const;

    // Request a Zone enrollment from the client (Server to client)
    ZigbeeClusterReply *sendZoneEnrollRequest(ZigbeeClusterIasZone::ZoneType zoneType, quint16 manufacturerCode);
    // Enroll a Zone on the server (Client to server)
    ZigbeeClusterReply *sendZoneEnrollResponse(quint8 zoneId, ZigbeeClusterIasZone::EnrollResponseCode code = EnrollResponseCodeSuccess);
    // Inform the client of Zone status changes (Server to client)
    ZigbeeClusterReply *sendZoneStatusChangeNotification(ZoneStatus status, quint8 zoneId, quint16 delay = 0);
private:
    ZoneState m_zoneState = ZoneStateNotEnrolled;
    ZoneType m_zoneType = ZoneTypeInvalidZone;
    ZoneStatusFlags m_zoneStatus;

    void setAttribute(const ZigbeeClusterAttribute &attribute) override;

protected:
    void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;

signals:
    void zoneStatusChanged(ZoneStatusFlags zoneStatus, quint8 extendedStatus, quint8 zoneId, quint16 delay);
    void zoneEnrollRequest(ZoneType zoneType, quint16 manufacturerCode, quint8 transactionSequenceNumber);

};

#endif // ZIGBEECLUSTERIASZONE_H
