#pragma once

#include <AK/Error.h>
#include <AK/MemoryStream.h>
#include <AK/OwnPtr.h>
#include <AK/Platform.h>
#include <AK/Result.h>
#include <AK/Utf8View.h>
#include <LibIPC/Attachment.h>
#include <LibIPC/Connection.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibIPC/File.h>
#include <LibIPC/Message.h>
#include <LibIPC/Stub.h>

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdefaulted-function-deleted"
#endif

namespace Messages::UIProcessClient {

enum class MessageID : i32 {
};

} // namespace Messages::UIProcessClient

template<typename LocalEndpoint, typename PeerEndpoint>
class UIProcessClientProxy {
public:
    // Used to disambiguate the constructor call.
    struct Tag { };

    UIProcessClientProxy(IPC::Connection<LocalEndpoint, PeerEndpoint>& connection, Tag)
        : m_connection(connection)
    {
    }

private:
    IPC::Connection<LocalEndpoint, PeerEndpoint>& m_connection;
};

template<typename LocalEndpoint, typename PeerEndpoint>
class UIProcessClientProxy;
class UIProcessClientStub;

class UIProcessClientEndpoint {
public:
    template<typename LocalEndpoint>
    using Proxy = UIProcessClientProxy<LocalEndpoint, UIProcessClientEndpoint>;
    using Stub = UIProcessClientStub;

    static u32 static_magic() { return 3596530658; }

    static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Queue<IPC::Attachment>& attachments)
    {
        FixedMemoryStream stream { buffer };
        auto message_endpoint_magic = TRY(stream.read_value<u32>());

        if (message_endpoint_magic != static_magic())
            return Error::from_string_literal("Endpoint magic number mismatch, not my message!");

        auto message_id = TRY(stream.read_value<i32>());

        switch (message_id) {
        default:
            return Error::from_string_literal("Failed to decode UIProcessClient message");
        }

        VERIFY_NOT_REACHED();
    }
};

class UIProcessClientStub : public IPC::Stub {
public:
    UIProcessClientStub() { }
    virtual ~UIProcessClientStub() override { }

    virtual u32 magic() const override { return 3596530658; }
    virtual ByteString name() const override { return "UIProcessClient"; }

    virtual ErrorOr<OwnPtr<IPC::MessageBuffer>> handle(NonnullOwnPtr<IPC::Message> message) override
    {
        switch (message->message_id()) {
        default:
            return Error::from_string_literal("Unknown message ID for UIProcessClient endpoint");
        }
    }

};

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic pop
#endif
