/*
 * 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.
 */

#pragma once

#import <Network/Network.h>
#import <experimental/coroutine>
#import <wtf/CompletionHandler.h>
#import <wtf/Forward.h>
#import <wtf/HashMap.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/StringHash.h>

OBJC_CLASS NSURLRequest;

namespace TestWebKitAPI {

class Connection;
struct HTTPResponse;

template<typename PromiseType>
struct CoroutineHandle {
    CoroutineHandle(std::experimental::coroutine_handle<PromiseType>&& handle)
        : handle(WTFMove(handle)) { }
    CoroutineHandle(const CoroutineHandle&) = delete;
    CoroutineHandle(CoroutineHandle&& other)
        : handle(std::exchange(other.handle, nullptr)) { }
    ~CoroutineHandle()
    {
        if (handle)
            handle.destroy();
    }
    std::experimental::coroutine_handle<PromiseType> handle;
};

struct Task {
    struct promise_type {
        Task get_return_object() { return { std::experimental::coroutine_handle<promise_type>::from_promise(*this) }; }
        std::experimental::suspend_never initial_suspend() { return { }; }
        std::experimental::suspend_never final_suspend() noexcept { return { }; }
        void unhandled_exception() { }
        void return_void() { }
    };
    CoroutineHandle<promise_type> handle;
};

class ReceiveOperation;
class SendOperation;

class HTTPServer {
    WTF_MAKE_FAST_ALLOCATED;
public:
    struct RequestData;
    enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2, HttpsProxy, HttpsProxyWithAuthentication };
    using CertificateVerifier = Function<void(sec_protocol_metadata_t, sec_trust_t, sec_protocol_verify_complete_t)>;

    HTTPServer(std::initializer_list<std::pair<String, HTTPResponse>>, Protocol = Protocol::Http, CertificateVerifier&& = nullptr, RetainPtr<SecIdentityRef>&& = nullptr, std::optional<uint16_t> port = { });
    HTTPServer(Function<void(Connection)>&&, Protocol = Protocol::Http);
    enum class UseCoroutines : bool { Yes };
    HTTPServer(UseCoroutines, Function<Task(Connection)>&&, Protocol = Protocol::Http);
    ~HTTPServer();
    uint16_t port() const;
    String origin() const;
    NSURLRequest *request(StringView path = "/"_s) const;
    NSURLRequest *requestWithLocalhost(StringView path = "/"_s) const;
    size_t totalRequests() const;
    void cancel();

    void addResponse(String&& path, HTTPResponse&&);
    void setResponse(String&& path, HTTPResponse&&);

    static void respondWithOK(Connection);
    static void respondWithChallengeThenOK(Connection);
    static String parsePath(const Vector<char>& request);
    static String parseBody(const Vector<char>&);
    static Vector<uint8_t> testPrivateKey();
    static Vector<uint8_t> testCertificate();

private:
    static RetainPtr<nw_parameters_t> listenerParameters(Protocol, CertificateVerifier&&, RetainPtr<SecIdentityRef>&&, std::optional<uint16_t> port);
    static void respondToRequests(Connection, Ref<RequestData>);
    const char* scheme() const;

    Ref<RequestData> m_requestData;
    RetainPtr<nw_listener_t> m_listener;
    Protocol m_protocol { Protocol::Http };
};

class Connection {
public:
    void send(String&&, CompletionHandler<void()>&& = nullptr) const;
    void send(Vector<uint8_t>&&, CompletionHandler<void()>&& = nullptr) const;
    void send(RetainPtr<dispatch_data_t>&&, CompletionHandler<void(bool)>&& = nullptr) const;
    SendOperation awaitableSend(Vector<uint8_t>&&);
    SendOperation awaitableSend(String&&);
    void sendAndReportError(Vector<uint8_t>&&, CompletionHandler<void(bool)>&&) const;
    void receiveBytes(CompletionHandler<void(Vector<uint8_t>&&)>&&, size_t minimumSize = 1) const;
    void receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&&, Vector<char>&& buffer = { }) const;
    ReceiveOperation awaitableReceiveHTTPRequest() const;
    void webSocketHandshake(CompletionHandler<void()>&& = { });
    void terminate(CompletionHandler<void()>&& = { });
    void cancel();

private:
    friend class HTTPServer;
    Connection(nw_connection_t connection)
        : m_connection(connection) { }

    RetainPtr<nw_connection_t> m_connection;
};

class ReceiveOperation : public std::experimental::suspend_never {
public:
    ReceiveOperation(const Connection& connection)
        : m_connection(connection) { }
    bool await_ready() { return false; }
    void await_suspend(std::experimental::coroutine_handle<>);
    Vector<char> await_resume() { return WTFMove(m_result); }
private:
    Connection m_connection;
    Vector<char> m_result;
};

class SendOperation : public std::experimental::suspend_never {
public:
    SendOperation(RetainPtr<dispatch_data_t>&& data, const Connection& connection)
        : m_data(WTFMove(data))
        , m_connection(connection) { }
    bool await_ready() { return false; }
    void await_suspend(std::experimental::coroutine_handle<>);
private:
    RetainPtr<dispatch_data_t> m_data;
    Connection m_connection;
};

struct HTTPResponse {
    enum class TerminateConnection { No, Yes };

    HTTPResponse(Vector<uint8_t>&& body)
        : body(WTFMove(body)) { }
    HTTPResponse(const String& body)
        : body(bodyFromString(body)) { }
    HTTPResponse(HashMap<String, String>&& headerFields, const String& body)
        : headerFields(WTFMove(headerFields))
        , body(bodyFromString(body)) { }
    HTTPResponse(unsigned statusCode, HashMap<String, String>&& headerFields = { }, const String& body = { })
        : statusCode(statusCode)
        , headerFields(WTFMove(headerFields))
        , body(bodyFromString(body)) { }
    HTTPResponse(TerminateConnection terminateConnection)
        : terminateConnection(terminateConnection) { }

    HTTPResponse(const HTTPResponse&) = default;
    HTTPResponse(HTTPResponse&&) = default;
    HTTPResponse() = default;
    HTTPResponse& operator=(const HTTPResponse&) = default;
    HTTPResponse& operator=(HTTPResponse&&) = default;

    enum class IncludeContentLength : bool { No, Yes };
    Vector<uint8_t> serialize(IncludeContentLength = IncludeContentLength::Yes) const;
    static Vector<uint8_t> bodyFromString(const String&);

    unsigned statusCode { 200 };
    HashMap<String, String> headerFields;
    Vector<uint8_t> body;
    TerminateConnection terminateConnection { TerminateConnection::No };
};

namespace H2 {

// https://http2.github.io/http2-spec/#rfc.section.4.1
class Frame {
public:

    // https://http2.github.io/http2-spec/#rfc.section.6
    enum class Type : uint8_t {
        Data = 0x0,
        Headers = 0x1,
        Priority = 0x2,
        RSTStream = 0x3,
        Settings = 0x4,
        PushPromise = 0x5,
        Ping = 0x6,
        GoAway = 0x7,
        WindowUpdate = 0x8,
        Continuation = 0x9,
    };

    Frame(Type type, uint8_t flags, uint32_t streamID, Vector<uint8_t> payload)
        : m_type(type)
        , m_flags(flags)
        , m_streamID(streamID)
        , m_payload(WTFMove(payload)) { }

    Type type() const { return m_type; }
    uint8_t flags() const { return m_flags; }
    uint32_t streamID() const { return m_streamID; }
    const Vector<uint8_t>& payload() const { return m_payload; }

private:
    Type m_type;
    uint8_t m_flags;
    uint32_t m_streamID;
    Vector<uint8_t> m_payload;
};

class Connection : public RefCounted<Connection> {
public:
    static Ref<Connection> create(TestWebKitAPI::Connection tlsConnection) { return adoptRef(*new Connection(tlsConnection)); }
    void send(Frame&&, CompletionHandler<void()>&& = nullptr) const;
    void receive(CompletionHandler<void(Frame&&)>&&) const;
private:
    Connection(TestWebKitAPI::Connection tlsConnection)
        : m_tlsConnection(tlsConnection) { }

    TestWebKitAPI::Connection m_tlsConnection;
    mutable bool m_expectClientConnectionPreface { true };
    mutable bool m_sendServerConnectionPreface { true };
    mutable Vector<uint8_t> m_receiveBuffer;
};

} // namespace H2

} // namespace TestWebKitAPI

RetainPtr<SecCertificateRef> testCertificate();
RetainPtr<SecIdentityRef> testIdentity();
RetainPtr<SecIdentityRef> testIdentity2();
