// Copyright 2019 The Dawn 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.

#ifndef DAWNWIRE_WIRESERVER_H_
#define DAWNWIRE_WIRESERVER_H_

#include <memory>

#include "dawn/wire/Wire.h"

struct DawnProcTable;

namespace dawn::wire {

    namespace server {
        class Server;
        class MemoryTransferService;
    }  // namespace server

    struct DAWN_WIRE_EXPORT WireServerDescriptor {
        const DawnProcTable* procs;
        CommandSerializer* serializer;
        server::MemoryTransferService* memoryTransferService = nullptr;
    };

    class DAWN_WIRE_EXPORT WireServer : public CommandHandler {
      public:
        WireServer(const WireServerDescriptor& descriptor);
        ~WireServer() override;

        const volatile char* HandleCommands(const volatile char* commands,
                                            size_t size) override final;

        bool InjectTexture(WGPUTexture texture,
                           uint32_t id,
                           uint32_t generation,
                           uint32_t deviceId,
                           uint32_t deviceGeneration);
        bool InjectSwapChain(WGPUSwapChain swapchain,
                             uint32_t id,
                             uint32_t generation,
                             uint32_t deviceId,
                             uint32_t deviceGeneration);

        bool InjectDevice(WGPUDevice device, uint32_t id, uint32_t generation);

        bool InjectInstance(WGPUInstance instance, uint32_t id, uint32_t generation);

        // Look up a device by (id, generation) pair. Returns nullptr if the generation
        // has expired or the id is not found.
        // The Wire does not have destroy hooks to allow an embedder to observe when an object
        // has been destroyed, but in Chrome, we need to know the list of live devices so we
        // can call device.Tick() on all of them periodically to ensure progress on asynchronous
        // work is made. Getting this list can be done by tracking the (id, generation) of
        // previously injected devices, and observing if GetDevice(id, generation) returns non-null.
        WGPUDevice GetDevice(uint32_t id, uint32_t generation);

      private:
        std::unique_ptr<server::Server> mImpl;
    };

    namespace server {
        class DAWN_WIRE_EXPORT MemoryTransferService {
          public:
            MemoryTransferService();
            virtual ~MemoryTransferService();

            class ReadHandle;
            class WriteHandle;

            // Deserialize data to create Read/Write handles. These handles are for the client
            // to Read/Write data.
            virtual bool DeserializeReadHandle(const void* deserializePointer,
                                               size_t deserializeSize,
                                               ReadHandle** readHandle) = 0;
            virtual bool DeserializeWriteHandle(const void* deserializePointer,
                                                size_t deserializeSize,
                                                WriteHandle** writeHandle) = 0;

            class DAWN_WIRE_EXPORT ReadHandle {
              public:
                ReadHandle();
                virtual ~ReadHandle();

                // Return the size of the command serialized if
                // SerializeDataUpdate is called with the same offset/size args
                virtual size_t SizeOfSerializeDataUpdate(size_t offset, size_t size) = 0;

                // Gets called when a MapReadCallback resolves.
                // Serialize the data update for the range (offset, offset + size) into
                // |serializePointer| to the client There could be nothing to be serialized (if
                // using shared memory)
                virtual void SerializeDataUpdate(const void* data,
                                                 size_t offset,
                                                 size_t size,
                                                 void* serializePointer) = 0;

              private:
                ReadHandle(const ReadHandle&) = delete;
                ReadHandle& operator=(const ReadHandle&) = delete;
            };

            class DAWN_WIRE_EXPORT WriteHandle {
              public:
                WriteHandle();
                virtual ~WriteHandle();

                // Set the target for writes from the client. DeserializeFlush should copy data
                // into the target.
                void SetTarget(void* data);
                // Set Staging data length for OOB check
                void SetDataLength(size_t dataLength);

                // This function takes in the serialized result of
                // client::MemoryTransferService::WriteHandle::SerializeDataUpdate.
                // Needs to check potential offset/size OOB and overflow
                virtual bool DeserializeDataUpdate(const void* deserializePointer,
                                                   size_t deserializeSize,
                                                   size_t offset,
                                                   size_t size) = 0;

              protected:
                void* mTargetData = nullptr;
                size_t mDataLength = 0;

              private:
                WriteHandle(const WriteHandle&) = delete;
                WriteHandle& operator=(const WriteHandle&) = delete;
            };

          private:
            MemoryTransferService(const MemoryTransferService&) = delete;
            MemoryTransferService& operator=(const MemoryTransferService&) = delete;
        };
    }  // namespace server

}  // namespace dawn::wire

#endif  // DAWNWIRE_WIRESERVER_H_
