/*
 * Copyright (C) 2010-2020 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.
 */

#pragma once

#include "AccessibilityController.h"
#include "EventSendingController.h"
#include "GCController.h"
#include "TestRunner.h"
#include "TextInputController.h"
#include <WebKit/WKBase.h>
#include <WebKit/WKBundlePage.h>
#include <WebKit/WKRetainPtr.h>
#include <sstream>
#include <wtf/Forward.h>
#include <wtf/Function.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>

namespace WTR {

class InjectedBundlePage;

class InjectedBundle {
public:
    static InjectedBundle& singleton();

    // Initialize the InjectedBundle.
    void initialize(WKBundleRef, WKTypeRef initializationUserData);

    WKBundleRef bundle() const { return m_bundle.get(); }

    TestRunner* testRunner() { return m_testRunner.get(); }
    GCController* gcController() { return m_gcController.get(); }
    EventSendingController* eventSendingController() { return m_eventSendingController.get(); }
    TextInputController* textInputController() { return m_textInputController.get(); }
    AccessibilityController* accessibilityController() { return m_accessibilityController.get(); }

    InjectedBundlePage* page() const;
    WKBundlePageRef pageRef() const;
    uint64_t testIdentifier() const { return m_testIdentifier; }
    size_t pageCount() const { return m_pages.size(); }

    void dumpBackForwardListsForAllPages(StringBuilder&);

    void done();
    void setAudioResult(WKDataRef audioData) { m_audioResult = audioData; }
    void setPixelResult(WKImageRef image) { m_pixelResult = image; m_pixelResultIsPending = false; }
    void setPixelResultIsPending(bool isPending) { m_pixelResultIsPending = isPending; }
    void setRepaintRects(WKArrayRef rects) { m_repaintRects = rects; }

    bool isTestRunning() { return !!testRunner(); }

    bool shouldDumpPixels() const { return m_dumpPixels; }

    enum class IsFinalTestOutput : bool { No, Yes };
    void outputText(StringView, IsFinalTestOutput = IsFinalTestOutput::No);
    void postNewBeforeUnloadReturnValue(bool);
    void postSetWindowIsKey(bool);
    void postSetViewSize(double width, double height);
    void postSimulateWebNotificationClick(WKDataRef notificationID);
    void postSimulateWebNotificationClickForServiceWorkerNotifications();
    void postSetAddsVisitedLinks(bool);

    // Geolocation.
    void setGeolocationPermission(bool);
    void setMockGeolocationPosition(double latitude, double longitude, double accuracy, std::optional<double> altitude, std::optional<double> altitudeAccuracy, std::optional<double> heading, std::optional<double> speed, std::optional<double> floorLevel);
    void setMockGeolocationPositionUnavailableError(WKStringRef errorMessage);
    bool isGeolocationProviderActive() const;

    // Screen Wake Lock.
    void setScreenWakeLockPermission(bool);

    // MediaStream.
    void setCameraPermission(bool);
    void setMicrophonePermission(bool);
    void resetUserMediaPermission();
    void delayUserMediaRequestDecision();
    unsigned userMediaPermissionRequestCount() const;
    void resetUserMediaPermissionRequestCount();

    // Policy delegate.
    void setCustomPolicyDelegate(bool enabled, bool permissive);

    // Page Visibility.
    void setHidden(bool);

    // Cache.
    void setCacheModel(int);

    // Work queue.
    bool shouldProcessWorkQueue() const;
    void processWorkQueue();
    void queueBackNavigation(unsigned howFarBackward);
    void queueForwardNavigation(unsigned howFarForward);
    void queueLoad(WKStringRef url, WKStringRef target, bool shouldOpenExternalURLs = false);
    void queueLoadHTMLString(WKStringRef content, WKStringRef baseURL = 0, WKStringRef unreachableURL = 0);
    void queueReload();
    void queueLoadingScript(WKStringRef script);
    void queueNonLoadingScript(WKStringRef script);

    bool isAllowedHost(WKStringRef);

    bool isPrinting() const;

    unsigned imageCountInGeneralPasteboard() const;

    void setAllowsAnySSLCertificate(bool);

    void statisticsNotifyObserver(CompletionHandler<void()>&&);

    void textDidChangeInTextField();
    void textFieldDidBeginEditing();
    void textFieldDidEndEditing();

    void reportLiveDocuments(WKBundlePageRef);

    void resetUserScriptInjectedCount() { m_userScriptInjectedCount = 0; }
    void increaseUserScriptInjectedCount() { ++m_userScriptInjectedCount; }
    size_t userScriptInjectedCount() const { return m_userScriptInjectedCount; }

    void clearResourceLoadStatistics();
    void reloadFromOrigin();

    WKRetainPtr<WKStringRef> getBackgroundFetchIdentifier();
    WKRetainPtr<WKStringRef> lastAddedBackgroundFetchIdentifier() const;
    WKRetainPtr<WKStringRef> lastRemovedBackgroundFetchIdentifier() const;
    WKRetainPtr<WKStringRef> lastProvisionalNavigationFailureURL() const;
    WKRetainPtr<WKStringRef> lastUpdatedBackgroundFetchIdentifier() const;
    WKRetainPtr<WKStringRef> backgroundFetchState(WKStringRef);

    bool shouldForceRepaint() const;

private:
    InjectedBundle() = default;
    ~InjectedBundle();

    static void didCreatePage(WKBundleRef, WKBundlePageRef, const void* clientInfo);
    static void willDestroyPage(WKBundleRef, WKBundlePageRef, const void* clientInfo);
    static void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo);
    static void didReceiveMessageToPage(WKBundleRef, WKBundlePageRef, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo);

    void didCreatePage(WKBundlePageRef);
    void willDestroyPage(WKBundlePageRef);
    void didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody);
    void didReceiveMessageToPage(WKBundlePageRef, WKStringRef messageName, WKTypeRef messageBody);

    void setUpInjectedBundleClients(WKBundlePageRef);

    void setAllowedHosts(WKDictionaryRef settings);

    void platformInitialize(WKTypeRef initializationUserData);

    enum class BegingTestingMode { New, Resume };
    void beginTesting(WKDictionaryRef initialSettings, BegingTestingMode);

    WKRetainPtr<WKBundleRef> m_bundle;
    Vector<std::unique_ptr<InjectedBundlePage>> m_pages;

    RefPtr<AccessibilityController> m_accessibilityController;
    RefPtr<TestRunner> m_testRunner;
    RefPtr<GCController> m_gcController;
    RefPtr<EventSendingController> m_eventSendingController;
    RefPtr<TextInputController> m_textInputController;

    bool m_dumpPixels { false };
    bool m_pixelResultIsPending { false };
    bool m_accessibilityIsolatedTreeMode { false };
    uint64_t m_testIdentifier { 0 };

    WTF::Seconds m_timeout;

    WKRetainPtr<WKDataRef> m_audioResult;
    WKRetainPtr<WKImageRef> m_pixelResult;
    WKRetainPtr<WKArrayRef> m_repaintRects;

    Vector<String> m_allowedHosts;

    size_t m_userScriptInjectedCount { 0 };

    WKRetainPtr<WKCaptionUserPreferencesTestingModeTokenRef> m_captionUserPreferencesTestingModeToken;
};

void postMessage(const char* name);
void postMessage(const char* name, bool value);
void postMessage(const char* name, int value);
void postMessage(const char* name, unsigned value);
void postMessage(const char* name, uint64_t value);
void postMessage(const char* name, const char* value);
void postMessage(const char* name, JSStringRef value);
void postMessage(const char* name, const void* value) = delete;

void postSynchronousMessage(const char* name);
void postSynchronousMessage(const char* name, bool value);
void postSynchronousMessage(const char* name, int value);
void postSynchronousMessage(const char* name, unsigned value);
void postSynchronousMessage(const char* name, uint64_t value);
void postSynchronousMessage(const char* name, double value);
void postSynchronousMessage(const char* name, const char* value);
void postSynchronousMessage(const char* name, const void* value) = delete;

void postPageMessage(const char* name);
void postPageMessage(const char* name, bool value);
void postPageMessage(const char* name, unsigned value);
void postPageMessage(const char* name, const char* value);
void postPageMessage(const char* name, WKStringRef value);
void postPageMessage(const char* name, WKDataRef value);
void postPageMessage(const char* name, const void* value) = delete;

void postSynchronousPageMessage(const char* name);
void postSynchronousPageMessage(const char* name, bool value);
void postSynchronousPageMessage(const char* name, const char* value);
void postSynchronousPageMessage(const char* name, const void* value) = delete;

template<typename T> void postMessage(const char* name, const WKRetainPtr<T>& value)
{
    WKBundlePostMessage(InjectedBundle::singleton().bundle(), toWK(name).get(), value.get());
}

template<typename T> void postSynchronousMessage(const char* name, const WKRetainPtr<T>& value)
{
    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), toWK(name).get(), value.get(), nullptr);
    ALLOW_DEPRECATED_DECLARATIONS_END
}

template<typename T> void postPageMessage(const char* name, const WKRetainPtr<T>& value)
{
    if (auto page = InjectedBundle::singleton().pageRef())
        WKBundlePagePostMessage(page, toWK(name).get(), value.get());
}

template<typename T> void postSynchronousPageMessage(const char* name, const WKRetainPtr<T>& value)
{
    if (auto page = InjectedBundle::singleton().pageRef()) {
        // EventSender needs a layout
        if (!strcmp(name, "EventSender"))
            WKBundlePageLayoutIfNeeded(page);
        WKBundlePagePostSynchronousMessageForTesting(page, toWK(name).get(), value.get(), nullptr);
    }
}
} // namespace WTR
