/*
 *   Copyright (c) 2022 Project CHIP Authors
 *   All rights reserved.
 *
 *   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.
 *
 */

#pragma once

#include "ModelCommandBridge.h"

class ReadAttribute : public ModelCommand {
public:
    ReadAttribute()
        : ModelCommand("read-by-id")
    {
        AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
        AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
        AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
        ModelCommand::AddArguments();
    }

    ReadAttribute(chip::ClusterId clusterId)
        : ModelCommand("read-by-id")
        , mClusterId(clusterId)
    {
        AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
        AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
        ModelCommand::AddArguments();
    }

    ReadAttribute(const char * _Nonnull attributeName)
        : ModelCommand("read")
    {
        AddArgument("attr-name", attributeName);
        AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
        ModelCommand::AddArguments();
    }

    ~ReadAttribute() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId) override
    {
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [device
            readAttributesWithEndpointID:[NSNumber numberWithUnsignedShort:endpointId]
                               clusterID:[NSNumber numberWithUnsignedInteger:mClusterId]
                             attributeID:[NSNumber numberWithUnsignedInteger:mAttributeId]
                                  params:params
                                   queue:callbackQueue
                              completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
                                  if (error != nil) {
                                      LogNSError("Error reading attribute", error);
                                  }
                                  if (values) {
                                      for (id item in values) {
                                          NSLog(@"Response Item: %@", [item description]);
                                      }
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }

protected:
    chip::Optional<bool> mFabricFiltered;

private:
    chip::ClusterId mClusterId;
    chip::AttributeId mAttributeId;
};

class SubscribeAttribute : public ModelCommand {
public:
    SubscribeAttribute()
        : ModelCommand("subscribe-by-id")
    {
        AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
        AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
        AddCommonArguments();
    }

    SubscribeAttribute(chip::ClusterId clusterId)
        : ModelCommand("subscribe-by-id")
        , mClusterId(clusterId)
    {
        AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
        AddCommonArguments();
    }

    SubscribeAttribute(const char * _Nonnull attributeName)
        : ModelCommand("subscribe")
    {
        AddArgument("attr-name", attributeName);
        AddCommonArguments();
    }

    void AddCommonArguments()
    {
        AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval);
        AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval);
        AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
        AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions);
        AddArgument("autoResubscribe", 0, 1, &mAutoResubscribe);
        ModelCommand::AddArguments();
    }

    ~SubscribeAttribute() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId) override
    {
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);

        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeIfLost = mAutoResubscribe.Value();
        }

        [device subscribeToAttributesWithEndpointID:[NSNumber numberWithUnsignedShort:endpointId]
            clusterID:[NSNumber numberWithUnsignedInteger:mClusterId]
            attributeID:[NSNumber numberWithUnsignedInteger:mAttributeId]
            params:params
            queue:callbackQueue
            reportHandler:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
                if (values) {
                    for (id item in values) {
                        NSLog(@"Response Item: %@", [item description]);
                    }
                }
                SetCommandExitStatus(error);
            }
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }];

        return CHIP_NO_ERROR;
    }

    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); }

protected:
    chip::Optional<bool> mKeepSubscriptions;
    chip::Optional<bool> mAutoResubscribe;
    chip::Optional<bool> mFabricFiltered;
    bool mSubscriptionEstablished = NO;
    uint16_t mMinInterval;
    uint16_t mMaxInterval;

    void Shutdown() override
    {
        mSubscriptionEstablished = NO;
        ModelCommand::Shutdown();
    }

    bool DeferInteractiveCleanup() override { return mSubscriptionEstablished; }

private:
    chip::ClusterId mClusterId;
    chip::AttributeId mAttributeId;
};

class SubscribeEvent : public ModelCommand {
public:
    SubscribeEvent()
        : ModelCommand("subscribe-all-events")
    {
        AddCommonArguments();
    }

    SubscribeEvent(chip::ClusterId clusterId, bool isClusterAny = false)
        : ModelCommand("subscribe-event-by-id")
        , mClusterId(clusterId)
    {
        if (isClusterAny == true) {
            AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
        }
        AddArgument("event-id", 0, UINT32_MAX, &mEventId);
        AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
        AddArgument("is-urgent", 0, 1, &mIsUrgent);
        AddCommonArguments();
    }

    void AddCommonArguments()
    {
        AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval);
        AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval);
        AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions);
        AddArgument("autoResubscribe", 0, 1, &mAutoResubscribe);
        ModelCommand::AddArguments();
    }

    ~SubscribeEvent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId) override
    {
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);

        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mEventNumber.HasValue()) {
            params.minimumEventNumber = [NSNumber numberWithUnsignedLongLong:mEventNumber.Value()];
        }
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mIsUrgent.HasValue()) {
            params.reportEventsUrgently = mIsUrgent.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeIfLost = mAutoResubscribe.Value();
        }

        if (strcmp(GetName(), "subscribe-event-by-id") == 0) {
            [device subscribeToEventsWithEndpointID:(endpointId == chip::kInvalidEndpointId)
                        ? nil
                        : [NSNumber numberWithUnsignedShort:endpointId]
                clusterID:(mClusterId == chip::kInvalidClusterId) ? nil : [NSNumber numberWithUnsignedInteger:mClusterId]
                eventID:(mEventId == chip::kInvalidEventId) ? nil : [NSNumber numberWithUnsignedInteger:mEventId]
                params:params
                queue:callbackQueue
                reportHandler:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
                    if (values) {
                        for (id item in values) {
                            NSLog(@"Response Item: %@", [item description]);
                        }
                    }
                    SetCommandExitStatus(error);
                }
                subscriptionEstablished:^() {
                    mSubscriptionEstablished = YES;
                }];
        } else {
            [device subscribeWithQueue:callbackQueue
                params:params
                clusterStateCacheContainer:nil
                attributeReportHandler:^(NSArray * value) {
                    SetCommandExitStatus(CHIP_NO_ERROR);
                }
                eventReportHandler:^(NSArray * value) {
                    for (id item in value) {
                        NSLog(@"Response Item: %@", [item description]);
                    }
                    SetCommandExitStatus(CHIP_NO_ERROR);
                }
                errorHandler:^(NSError * error) {
                    SetCommandExitStatus(error);
                }
                subscriptionEstablished:^() {
                    mSubscriptionEstablished = YES;
                }
                resubscriptionScheduled:^(NSError * error, NSNumber * resubscriptionDelay) {
                    NSLog(@"Subscription dropped with error %@.  Resubscription in %@ms", error, resubscriptionDelay);
                }];
        }

        return CHIP_NO_ERROR;
    }

    chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); }

protected:
    chip::Optional<bool> mKeepSubscriptions;
    chip::Optional<bool> mAutoResubscribe;
    chip::Optional<chip::EventNumber> mEventNumber;
    chip::Optional<bool> mIsUrgent;
    bool mSubscriptionEstablished = NO;
    uint16_t mMinInterval;
    uint16_t mMaxInterval;

    void Shutdown() override
    {
        mSubscriptionEstablished = NO;
        ModelCommand::Shutdown();
    }

    bool DeferInteractiveCleanup() override { return mSubscriptionEstablished; }

private:
    chip::ClusterId mClusterId;
    chip::EventId mEventId;
};

class ReadEvent : public ModelCommand {
public:
    ReadEvent()
        : ModelCommand("read-event-by-id")
    {
        AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
        AddArgument("event-id", 0, UINT32_MAX, &mEventId);
        AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
        ModelCommand::AddArguments();
    }

    ReadEvent(chip::ClusterId clusterId)
        : ModelCommand("read-event-by-id")
        , mClusterId(clusterId)
    {
        AddArgument("event-id", 0, UINT32_MAX, &mEventId);
        AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
        ModelCommand::AddArguments();
    }

    ~ReadEvent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId) override
    {
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mEventNumber.HasValue()) {
            params.minimumEventNumber = [NSNumber numberWithUnsignedLongLong:mEventNumber.Value()];
        }

        [device
            readEventsWithEndpointID:(endpointId == chip::kInvalidEndpointId) ? nil : [NSNumber numberWithUnsignedShort:endpointId]
                           clusterID:(mClusterId == chip::kInvalidClusterId) ? nil : [NSNumber numberWithUnsignedInteger:mClusterId]
                             eventID:(mEventId == chip::kInvalidEventId) ? nil : [NSNumber numberWithUnsignedInteger:mEventId]
                              params:params
                               queue:callbackQueue
                          completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
                              if (error != nil) {
                                  LogNSError("Error reading event", error);
                              }
                              if (values) {
                                  for (id item in values) {
                                      NSLog(@"Response Item: %@", [item description]);
                                  }
                              }
                              SetCommandExitStatus(error);
                          }];
        return CHIP_NO_ERROR;
    }

protected:
    chip::Optional<bool> mFabricFiltered;
    chip::Optional<chip::EventNumber> mEventNumber;

private:
    chip::ClusterId mClusterId;
    chip::AttributeId mEventId;
};
