// 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_
