/**
 *
 *    Copyright (c) 2022 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.
 */

// NOTE: This class was not intended to be part of the public Matter API;
// internally this class has been replaced by MTRAsyncWorkQueue. This code
// remains here simply to preserve API/ABI compatibility.

#import <dispatch/dispatch.h>
#import <os/lock.h>

#import "MTRLogging_Internal.h"
#import "MTRUnfairLock.h"

#import <Matter/MTRAsyncCallbackWorkQueue.h>

#pragma mark - Class extensions

@interface MTRAsyncCallbackWorkQueue ()
// The lock protects the internal state of the work queue so that these may be called from any queue or thread:
//   -enqueueWorkItem:
//   -invalidate
//   -endWork:
//   -retryWork:
@property (nonatomic, readonly) os_unfair_lock lock;
@property (nonatomic, strong, readonly) id context;
@property (nonatomic, strong, readonly) dispatch_queue_t queue;
@property (nonatomic, strong, readonly) NSMutableArray<MTRAsyncCallbackQueueWorkItem *> * items;
@property (nonatomic, readwrite) NSUInteger runningWorkItemCount;

// For WorkItem's use only - the parameter is for sanity check
- (void)endWork:(MTRAsyncCallbackQueueWorkItem *)workItem;
- (void)retryWork:(MTRAsyncCallbackQueueWorkItem *)workItem;
@end

@interface MTRAsyncCallbackQueueWorkItem ()
@property (nonatomic, readonly) os_unfair_lock lock;
@property (nonatomic, strong, readonly) dispatch_queue_t queue;
@property (nonatomic, readwrite) NSUInteger retryCount;
@property (nonatomic, strong) MTRAsyncCallbackWorkQueue * workQueue;
@property (nonatomic, readonly) BOOL enqueued;
// Called by the queue
- (void)markEnqueued;
- (void)callReadyHandlerWithContext:(id)context;
- (void)cancel;
@end

#pragma mark - Class implementations

@implementation MTRAsyncCallbackWorkQueue
- (instancetype)initWithContext:(id)context queue:(dispatch_queue_t)queue
{
    if (self = [super init]) {
        _lock = OS_UNFAIR_LOCK_INIT;
        _context = context;
        _queue = queue;
        _items = [NSMutableArray array];
    }
    return self;
}

- (NSString *)description
{
    std::lock_guard lock(_lock);

    return [NSString
        stringWithFormat:@"MTRAsyncCallbackWorkQueue context: %@ items count: %lu", self.context, (unsigned long) self.items.count];
}

- (void)enqueueWorkItem:(MTRAsyncCallbackQueueWorkItem *)item
{
    if (item.enqueued) {
        MTR_LOG_ERROR("MTRAsyncCallbackWorkQueue enqueueWorkItem: item cannot be enqueued twice");
        return;
    }

    [item markEnqueued];

    std::lock_guard lock(_lock);
    item.workQueue = self;
    [self.items addObject:item];

    [self _callNextReadyWorkItem];
}

- (void)invalidate
{
    os_unfair_lock_lock(&_lock);
    NSMutableArray * invalidateItems = _items;
    _items = nil;
    os_unfair_lock_unlock(&_lock);

    for (MTRAsyncCallbackQueueWorkItem * item in invalidateItems) {
        [item cancel];
    }
    [invalidateItems removeAllObjects];
}

// called after executing a work item
- (void)_postProcessWorkItem:(MTRAsyncCallbackQueueWorkItem *)workItem retry:(BOOL)retry
{
    std::lock_guard lock(_lock);
    // sanity check if running
    if (!self.runningWorkItemCount) {
        // something is wrong with state - nothing is currently running
        MTR_LOG_ERROR("MTRAsyncCallbackWorkQueue endWork: no work is running on work queue");
        return;
    }

    // sanity check the same work item is running
    // when "concurrency width" is implemented need to check first N items
    MTRAsyncCallbackQueueWorkItem * firstWorkItem = self.items.firstObject;
    if (firstWorkItem != workItem) {
        // something is wrong with this work item - should not be currently running
        MTR_LOG_ERROR("MTRAsyncCallbackWorkQueue endWork: work item is not first on work queue");
        return;
    }

    // if work item is done (no need to retry), remove from queue and call ready on the next item
    if (!retry) {
        [self.items removeObjectAtIndex:0];
    }

    // when "concurrency width" is implemented this will be decremented instead
    self.runningWorkItemCount = 0;
    [self _callNextReadyWorkItem];
}

- (void)endWork:(MTRAsyncCallbackQueueWorkItem *)workItem
{
    [self _postProcessWorkItem:workItem retry:NO];
}

- (void)retryWork:(MTRAsyncCallbackQueueWorkItem *)workItem
{
    [self _postProcessWorkItem:workItem retry:YES];
}

// assume lock is held while calling this
- (void)_callNextReadyWorkItem
{
    // when "concurrency width" is implemented this will be checked against the width
    if (self.runningWorkItemCount) {
        // can't run next work item until the current one is done
        return;
    }

    // only proceed to mark queue as running if there are items to run
    if (self.items.count) {
        // when "concurrency width" is implemented this will be incremented instead
        self.runningWorkItemCount = 1;

        MTRAsyncCallbackQueueWorkItem * workItem = self.items.firstObject;
        [workItem callReadyHandlerWithContext:self.context];
    }
}

@end

@implementation MTRAsyncCallbackQueueWorkItem

- (instancetype)initWithQueue:(dispatch_queue_t)queue
{
    if (self = [super init]) {
        _lock = OS_UNFAIR_LOCK_INIT;
        _queue = queue;
    }
    return self;
}

// assume lock is held
- (void)_invalidate
{
    // Make sure we don't leak via handlers that close over us, as ours must.
    // This is a bit odd, since these are supposed to be non-nullable
    // properties, but it's the best we can do given our API surface, unless we
    // assume that all consumers consistently use __weak refs to us inside their
    // handlers.
    //
    // Setting the attributes to nil will not compile; set the ivars directly.
    _readyHandler = nil;
    _cancelHandler = nil;
}

- (void)invalidate
{
    std::lock_guard lock(_lock);
    [self _invalidate];
}

- (void)markEnqueued
{
    std::lock_guard lock(_lock);
    _enqueued = YES;
}

- (void)setReadyHandler:(MTRAsyncCallbackReadyHandler)readyHandler
{
    std::lock_guard lock(_lock);
    if (!_enqueued) {
        _readyHandler = readyHandler;
    }
}

- (void)setCancelHandler:(dispatch_block_t)cancelHandler
{
    std::lock_guard lock(_lock);
    if (!_enqueued) {
        _cancelHandler = cancelHandler;
    }
}

- (void)endWork
{
    [self.workQueue endWork:self];
    [self invalidate];
}

- (void)retryWork
{
    [self.workQueue retryWork:self];
}

// Called by the work queue
- (void)callReadyHandlerWithContext:(id)context
{
    dispatch_async(self.queue, ^{
        os_unfair_lock_lock(&self->_lock);
        MTRAsyncCallbackReadyHandler readyHandler = self->_readyHandler;
        NSUInteger retryCount = self->_retryCount;
        if (readyHandler) {
            self->_retryCount++;
        }
        os_unfair_lock_unlock(&self->_lock);

        if (readyHandler == nil) {
            // Nothing to do here.
            [self endWork];
        } else {
            readyHandler(context, retryCount);
        }
    });
}

// Called by the work queue
- (void)cancel
{
    os_unfair_lock_lock(&self->_lock);
    dispatch_block_t cancelHandler = self->_cancelHandler;
    [self _invalidate];
    os_unfair_lock_unlock(&self->_lock);

    if (cancelHandler) {
        dispatch_async(self.queue, ^{
            cancelHandler();
        });
    }
}

@end
