/*
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"
#import "ProcessTaskStateObserver.h"

#if PLATFORM(IOS_FAMILY)

#import "AssertionServicesSPI.h"
#import "Logging.h"
#import <wtf/Function.h>
#import <wtf/SoftLinking.h>

SOFT_LINK_PRIVATE_FRAMEWORK(AssertionServices);
SOFT_LINK_CLASS(AssertionServices, BKSProcess);

typedef void(^TaskStateChangedCallbackType)(BKSProcessTaskState);

@interface WKProcessTaskStateObserverDelegate : NSObject<BKSProcessDelegate>
@property (copy) TaskStateChangedCallbackType taskStateChangedCallback;
@end

@implementation WKProcessTaskStateObserverDelegate
- (void)process:(BKSProcess *)process taskStateDidChange:(BKSProcessTaskState)newState
{
    RELEASE_LOG(ProcessSuspension, "%p -[WKProcessTaskStateObserverDelegate process:taskStateDidChange:], process(%p), newState(%d)", self, process, (int)newState);

    if (auto callback = _taskStateChangedCallback)
        callback(newState);
}
@end

namespace WebKit {

static ProcessTaskStateObserver::TaskState toProcessTaskStateObserverTaskState(BKSProcessTaskState state)
{
    static_assert(static_cast<uint32_t>(BKSProcessTaskStateNone) == static_cast<uint32_t>(ProcessTaskStateObserver::None), "BKSProcessTaskState != ProcessTaskStateObserver::TaskState");
    static_assert(static_cast<uint32_t>(BKSProcessTaskStateRunning) == static_cast<uint32_t>(ProcessTaskStateObserver::Running), "BKSProcessTaskState != ProcessTaskStateObserver::TaskState");
    static_assert(static_cast<uint32_t>(BKSProcessTaskStateSuspended) == static_cast<uint32_t>(ProcessTaskStateObserver::Suspended), "BKSProcessTaskState != ProcessTaskStateObserver::TaskState");
    return static_cast<ProcessTaskStateObserver::TaskState>(state);
}

Ref<ProcessTaskStateObserver> ProcessTaskStateObserver::create(Client& client)
{
    return adoptRef(*new ProcessTaskStateObserver(client));
}

ProcessTaskStateObserver::ProcessTaskStateObserver(Client& client)
    : m_client(&client)
    , m_process([getBKSProcessClass() currentProcess])
    , m_delegate(adoptNS([[WKProcessTaskStateObserverDelegate alloc] init]))
{
    RELEASE_LOG(ProcessSuspension, "%p - ProcessTaskStateObserver::ProcessTaskStateObserver(), m_process(%p)", this, m_process.get());
    m_delegate.get().taskStateChangedCallback = [protectedThis = makeRefPtr(this)] (BKSProcessTaskState state) {
        protectedThis->setTaskState(toProcessTaskStateObserverTaskState(state));
    };
    m_process.get().delegate = m_delegate.get();
}

ProcessTaskStateObserver::~ProcessTaskStateObserver()
{
    m_delegate.get().taskStateChangedCallback = nil;
}

void ProcessTaskStateObserver::invalidate()
{
    LockHolder holder(m_clientLock);
    m_client = nullptr;
    m_delegate.get().taskStateChangedCallback = nil;
}

void ProcessTaskStateObserver::setTaskState(TaskState state)
{
    if (m_taskState == state)
        return;

    m_taskState = state;

    LockHolder holder(m_clientLock);
    if (m_client)
        m_client->processTaskStateDidChange(state);
}

}

#endif // PLATFORM(IOS_FAMILY)

