/**
 *
 *    Copyright (c) 2023 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *
 */
#include "dishwasher-alarm-server.h"

#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-enums.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app/EventLogging.h>
#include <app/InteractionModelEngine.h>
#include <app/util/attribute-storage.h>
#include <app/util/config.h>
#include <lib/support/BitFlags.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::DishwasherAlarm;
using namespace chip::app::Clusters::DishwasherAlarm::Attributes;
using namespace chip::DeviceLayer;
using chip::Protocols::InteractionModel::Status;
using namespace std;

static constexpr size_t kDishwasherAlarmDelegateTableSize =
    MATTER_DM_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;

static_assert(kDishwasherAlarmDelegateTableSize <= kEmberInvalidEndpointIndex, "Dishwasher Alarm Delegate table size error");

namespace chip {
namespace app {
namespace Clusters {
namespace DishwasherAlarm {

Delegate * gDelegateTable[kDishwasherAlarmDelegateTableSize] = { nullptr };

Delegate * GetDelegate(EndpointId endpoint)
{
    uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, DishwasherAlarm::Id,
                                                       MATTER_DM_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT);
    return (ep >= kDishwasherAlarmDelegateTableSize ? nullptr : gDelegateTable[ep]);
}

void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate)
{
    uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, DishwasherAlarm::Id,
                                                       MATTER_DM_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT);
    // if endpoint is found
    if (ep < kDishwasherAlarmDelegateTableSize)
    {
        gDelegateTable[ep] = delegate;
    }
}

} // namespace DishwasherAlarm
} // namespace Clusters
} // namespace app
} // namespace chip

DishwasherAlarmServer DishwasherAlarmServer::instance;

DishwasherAlarmServer & DishwasherAlarmServer::Instance()
{
    return instance;
}

Status DishwasherAlarmServer::GetMaskValue(EndpointId endpoint, BitMask<AlarmMap> * mask)
{
    Status status = Attributes::Mask::Get(endpoint, mask);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading  mask, err:0x%x", to_underlying(status));
        return status;
    }
    return status;
}

Status DishwasherAlarmServer::GetLatchValue(EndpointId endpoint, BitMask<AlarmMap> * latch)
{
    if (!HasResetFeature(endpoint))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm feature: Unsupport Latch attribute");
        return Status::UnsupportedAttribute;
    }

    Status status = Attributes::Latch::Get(endpoint, latch);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading  latch, err:0x%x", to_underlying(status));
        return status;
    }
    return status;
}

Status DishwasherAlarmServer::GetStateValue(EndpointId endpoint, BitMask<AlarmMap> * state)
{
    Status status = Attributes::State::Get(endpoint, state);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: get state, err:0x%x", to_underlying(status));
        return status;
    }
    return status;
}

Status DishwasherAlarmServer::GetSupportedValue(EndpointId endpoint, BitMask<AlarmMap> * supported)
{
    Status status = Attributes::Supported::Get(endpoint, supported);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading  supported, err:0x%x", to_underlying(status));
    }
    return status;
}

Status DishwasherAlarmServer::SetSupportedValue(EndpointId endpoint, const BitMask<AlarmMap> supported)
{
    Status status = Status::Success;

    if ((status = Attributes::Supported::Set(endpoint, supported)) != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing supported, err:0x%x", to_underlying(status));
        return status;
    }

    // Whenever there is change in Supported attribute, Latch should change accordingly (if possible).
    BitMask<AlarmMap> latch;
    if (GetLatchValue(endpoint, &latch) == Status::Success && !supported.HasAll(latch))
    {
        latch  = latch & supported;
        status = SetLatchValue(endpoint, latch);
    }

    // Whenever there is change in Supported attribute, Mask, State should change accordingly.
    BitMask<AlarmMap> mask;
    if ((status = GetMaskValue(endpoint, &mask)) != Status::Success)
    {
        return status;
    }

    if (!supported.HasAll(mask))
    {
        mask   = supported & mask;
        status = SetMaskValue(endpoint, mask);
    }
    return status;
}

Status DishwasherAlarmServer::SetMaskValue(EndpointId endpoint, const BitMask<AlarmMap> mask)
{
    BitMask<AlarmMap> supported;
    if (Status::Success != GetSupportedValue(endpoint, &supported) || !supported.HasAll(mask))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Mask is not supported");
        return Status::Failure;
    }

    Status status = Status::Success;
    if ((status = Attributes::Mask::Set(endpoint, mask)) != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing  mask, err:0x%x", to_underlying(status));
        return status;
    }

    // Whenever there is change in Mask, State should change accordingly.
    BitMask<AlarmMap> state;
    status = GetStateValue(endpoint, &state);
    if (status != Status::Success)
    {
        return status;
    }

    if (!mask.HasAll(state))
    {
        state  = mask & state;
        status = SetStateValue(endpoint, state, true);
    }
    return status;
}

Status DishwasherAlarmServer::SetLatchValue(EndpointId endpoint, const BitMask<AlarmMap> latch)
{
    if (!HasResetFeature(endpoint))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm feature: Unsupport Latch attribute");
        return Status::UnsupportedAttribute;
    }

    BitMask<AlarmMap> supported;
    if (Status::Success != GetSupportedValue(endpoint, &supported) || !supported.HasAll(latch))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Latch is not supported");
        return Status::Failure;
    }

    Status status = Attributes::Latch::Set(endpoint, latch);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing  latch, err:0x%x", to_underlying(status));
        return status;
    }

    return status;
}

Status DishwasherAlarmServer::SetStateValue(EndpointId endpoint, const BitMask<AlarmMap> newState, bool ignoreLatchState)
{
    BitMask<AlarmMap> supported;
    BitMask<AlarmMap> finalNewState;
    finalNewState.Set(newState);

    if (Status::Success != GetSupportedValue(endpoint, &supported) || !supported.HasAll(finalNewState))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Alarm is not supported");
        return Status::Failure;
    }

    BitMask<AlarmMap> mask;
    if (Status::Success != GetMaskValue(endpoint, &mask) || !mask.HasAll(finalNewState))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Alarm is suppressed");
        return Status::Failure;
    }

    Status status = Status::Success;
    BitMask<AlarmMap> currentState;
    status = Attributes::State::Get(endpoint, &currentState);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading  state, err:0x%x", to_underlying(status));
        return status;
    }

    BitMask<AlarmMap> latch;
    if (!ignoreLatchState && (GetLatchValue(endpoint, &latch) == Status::Success))
    {
        // Restore bits that have their Latch bit set.
        auto bitsToKeep = latch & currentState;
        finalNewState.Set(bitsToKeep);
    }

    // Store the new value of the State attribute.
    status = Attributes::State::Set(endpoint, finalNewState);
    if (status != Status::Success)
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing  state, err:0x%x", to_underlying(status));
        return status;
    }

    // Generate Notify event.
    BitMask<AlarmMap> becameActive;
    becameActive.Set(finalNewState).Clear(currentState);
    BitMask<AlarmMap> becameInactive;
    becameInactive.Set(currentState).Clear(finalNewState);

    SendNotifyEvent(endpoint, becameActive, becameInactive, finalNewState, mask);
    return status;
}

Status DishwasherAlarmServer::ResetLatchedAlarms(EndpointId endpoint, const BitMask<AlarmMap> alarms)
{
    BitMask<AlarmMap> supported;
    if (Status::Success != GetSupportedValue(endpoint, &supported) || !supported.HasAll(alarms))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Alarm is not supported");
        return Status::Failure;
    }

    BitMask<AlarmMap> state;
    if (GetStateValue(endpoint, &state) != Status::Success)
    {
        return Status::Failure;
    }

    state.Clear(alarms);
    return SetStateValue(endpoint, state, true);
}

bool DishwasherAlarmServer::HasResetFeature(EndpointId endpoint)
{
    uint32_t featureMap = 0;
    if (Attributes::FeatureMap::Get(endpoint, &featureMap) != Status::Success)
    {
        return false;
    }

    if (featureMap & to_underlying(Feature::kReset))
    {
        return true;
    }
    return false;
}

void DishwasherAlarmServer::SendNotifyEvent(EndpointId endpointId, BitMask<AlarmMap> becameActive, BitMask<AlarmMap> becameInactive,
                                            BitMask<AlarmMap> newState, BitMask<AlarmMap> mask)
{
    Events::Notify::Type event{ .active = becameActive, .inactive = becameInactive, .state = newState, .mask = mask };
    EventNumber eventNumber;
    CHIP_ERROR error = LogEvent(event, endpointId, eventNumber);
    if (CHIP_NO_ERROR != error)
    {
        ChipLogError(Zcl, "[Notify] Unable to send notify event: %s [endpointId=%d]", error.AsString(), endpointId);
    }
}

static Status ModifyEnabledHandler(const app::ConcreteCommandPath & commandPath, const BitMask<AlarmMap> mask)
{
    EndpointId endpoint = commandPath.mEndpointId;
    BitMask<AlarmMap> supported;

    if (DishwasherAlarmServer::Instance().GetSupportedValue(endpoint, &supported) != Status::Success)
    {
        return Status::Failure;
    }

    // receives this command with a Mask that includes bits that are set for alarms which are not supported
    if (!supported.HasAll(mask))
    {
        return Status::InvalidCommand;
    }

    // A server that is unable to enable a currently suppressed alarm,
    // or is unable to suppress a currently enabled alarm SHALL respond
    // with a status code of FAILURE
    Delegate * delegate = DishwasherAlarm::GetDelegate(endpoint);
    if (delegate && !(delegate->ModifyEnabledAlarmsCallback(mask)))
    {
        ChipLogProgress(Zcl, "Unable to modify enabled alarms");
        return Status::Failure;
    }
    // The cluster will do this update if delegate.ModifyEnabledAlarmsCallback() returns true.
    if (DishwasherAlarmServer::Instance().SetMaskValue(endpoint, mask) != Status::Success)
    {
        return Status::Failure;
    }
    return Status::Success;
}

static Status ResetHandler(const app::ConcreteCommandPath & commandPath, const BitMask<AlarmMap> alarms)
{
    EndpointId endpoint = commandPath.mEndpointId;

    if (!DishwasherAlarmServer::Instance().HasResetFeature(endpoint))
    {
        ChipLogProgress(Zcl, "Dishwasher Alarm feature: Unsupport Reset Command");
        return Status::UnsupportedCommand;
    }

    // A server that is unable to reset alarms SHALL respond with a status code of FAILURE
    Delegate * delegate = DishwasherAlarm::GetDelegate(endpoint);
    if (delegate && !(delegate->ResetAlarmsCallback(alarms)))
    {
        ChipLogProgress(Zcl, "Unable to reset alarms");
        return Status::Failure;
    }

    // The cluster will do this update if delegate.ResetAlarmsCallback() returns true.
    if (DishwasherAlarmServer::Instance().ResetLatchedAlarms(endpoint, alarms) != Status::Success)
    {
        ChipLogProgress(Zcl, "reset alarms fail");
        return Status::Failure;
    }
    return Status::Success;
}

bool emberAfDishwasherAlarmClusterResetCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                                const Commands::Reset::DecodableType & commandData)
{
    auto & alarms = commandData.alarms;

    Status status = ResetHandler(commandPath, alarms);
    commandObj->AddStatus(commandPath, status);

    return true;
}

bool emberAfDishwasherAlarmClusterModifyEnabledAlarmsCallback(app::CommandHandler * commandObj,
                                                              const app::ConcreteCommandPath & commandPath,
                                                              const Commands::ModifyEnabledAlarms::DecodableType & commandData)
{
    auto & mask   = commandData.mask;
    Status status = ModifyEnabledHandler(commandPath, mask);
    commandObj->AddStatus(commandPath, status);

    return true;
}
