// Copyright 2021 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 SRC_DAWN_NODE_BINDING_GPUBUFFER_H_
#define SRC_DAWN_NODE_BINDING_GPUBUFFER_H_

#include "dawn/native/DawnNative.h"
#include "dawn/webgpu_cpp.h"
#include "node-addon-api/napi.h"
#include "src/dawn/node/binding/AsyncRunner.h"
#include "src/dawn/node/interop/WebGPU.h"

namespace wgpu::binding {

    // GPUBuffer is an implementation of interop::GPUBuffer that wraps a wgpu::Buffer.
    class GPUBuffer final : public interop::GPUBuffer {
      public:
        GPUBuffer(wgpu::Buffer buffer,
                  wgpu::BufferDescriptor desc,
                  wgpu::Device device,
                  std::shared_ptr<AsyncRunner> async);

        // Desc() returns the wgpu::BufferDescriptor used to construct the buffer
        const wgpu::BufferDescriptor& Desc() const {
            return desc_;
        }

        // Implicit cast operator to Dawn GPU object
        inline operator const wgpu::Buffer&() const {
            return buffer_;
        }

        // interop::GPUBuffer interface compliance
        interop::Promise<void> mapAsync(Napi::Env env,
                                        interop::GPUMapModeFlags mode,
                                        interop::GPUSize64 offset,
                                        std::optional<interop::GPUSize64> size) override;
        interop::ArrayBuffer getMappedRange(Napi::Env env,
                                            interop::GPUSize64 offset,
                                            std::optional<interop::GPUSize64> size) override;
        void unmap(Napi::Env) override;
        void destroy(Napi::Env) override;
        std::variant<std::string, interop::UndefinedType> getLabel(Napi::Env) override;
        void setLabel(Napi::Env, std::variant<std::string, interop::UndefinedType> value) override;

      private:
        void DetachMappings();

        struct Mapping {
            uint64_t start;
            uint64_t end;
            inline bool Intersects(uint64_t s, uint64_t e) const {
                return s < end && e > start;
            }
            Napi::Reference<interop::ArrayBuffer> buffer;
        };

        // https://www.w3.org/TR/webgpu/#buffer-interface
        enum class State {
            Unmapped,
            Mapped,
            MappedAtCreation,
            MappingPending,
            Destroyed,
        };

        wgpu::Buffer buffer_;
        wgpu::BufferDescriptor const desc_;
        wgpu::Device const device_;
        std::shared_ptr<AsyncRunner> async_;
        State state_ = State::Unmapped;
        std::vector<Mapping> mapped_;
    };

}  // namespace wgpu::binding

#endif  // SRC_DAWN_NODE_BINDING_GPUBUFFER_H_
