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

#include "src/dawn/node/binding/GPUBuffer.h"

#include <memory>
#include <utility>

#include "src/dawn/node/binding/Converter.h"
#include "src/dawn/node/binding/Errors.h"
#include "src/dawn/node/utils/Debug.h"

namespace wgpu::binding {

////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPUBuffer
// TODO(crbug.com/dawn/1134): We may be doing more validation here than necessary. Once CTS is
// robustly passing, pull out validation and see what / if breaks.
////////////////////////////////////////////////////////////////////////////////
GPUBuffer::GPUBuffer(wgpu::Buffer buffer,
                     wgpu::BufferDescriptor desc,
                     wgpu::Device device,
                     std::shared_ptr<AsyncRunner> async)
    : buffer_(std::move(buffer)),
      desc_(desc),
      device_(std::move(device)),
      async_(std::move(async)),
      label_(desc.label ? desc.label : "") {
    if (desc.mappedAtCreation) {
        state_ = State::MappedAtCreation;
    }
}

interop::Promise<void> GPUBuffer::mapAsync(Napi::Env env,
                                           interop::GPUMapModeFlags mode,
                                           interop::GPUSize64 offset,
                                           std::optional<interop::GPUSize64> size) {
    wgpu::MapMode md{};
    Converter conv(env);
    if (!conv(md, mode)) {
        interop::Promise<void> promise(env, PROMISE_INFO);
        promise.Reject(Errors::OperationError(env));
        return promise;
    }

    if (state_ != State::Unmapped) {
        interop::Promise<void> promise(env, PROMISE_INFO);
        promise.Reject(Errors::OperationError(env));
        device_.InjectError(wgpu::ErrorType::Validation,
                            "mapAsync called on buffer that is not in the unmapped state");
        return promise;
    }

    struct Context {
        Napi::Env env;
        interop::Promise<void> promise;
        AsyncTask task;
        State& state;
    };
    auto ctx =
        new Context{env, interop::Promise<void>(env, PROMISE_INFO), AsyncTask(async_), state_};
    auto promise = ctx->promise;

    uint64_t s = size.has_value() ? size.value().value : (desc_.size - offset);

    state_ = State::MappingPending;

    buffer_.MapAsync(
        md, offset, s,
        [](WGPUBufferMapAsyncStatus status, void* userdata) {
            auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));
            c->state = State::Unmapped;
            switch (status) {
                case WGPUBufferMapAsyncStatus_Force32:
                    UNREACHABLE("WGPUBufferMapAsyncStatus_Force32");
                    break;
                case WGPUBufferMapAsyncStatus_Success:
                    c->promise.Resolve();
                    c->state = State::Mapped;
                    break;
                case WGPUBufferMapAsyncStatus_ValidationError:
                    c->promise.Reject(Errors::OperationError(c->env));
                    break;
                case WGPUBufferMapAsyncStatus_UnmappedBeforeCallback:
                case WGPUBufferMapAsyncStatus_DestroyedBeforeCallback:
                case WGPUBufferMapAsyncStatus_MappingAlreadyPending:
                case WGPUBufferMapAsyncStatus_OffsetOutOfRange:
                case WGPUBufferMapAsyncStatus_SizeOutOfRange:
                    c->promise.Reject(Errors::AbortError(c->env));
                    break;
                case WGPUBufferMapAsyncStatus_Unknown:
                case WGPUBufferMapAsyncStatus_DeviceLost:
                    // TODO(dawn:1123): The spec is a bit vague around what the promise should
                    // do here.
                    c->promise.Reject(Errors::UnknownError(c->env));
                    break;
            }
        },
        ctx);

    return promise;
}

interop::ArrayBuffer GPUBuffer::getMappedRange(Napi::Env env,
                                               interop::GPUSize64 offset,
                                               std::optional<interop::GPUSize64> size) {
    if (state_ != State::Mapped && state_ != State::MappedAtCreation) {
        Errors::OperationError(env).ThrowAsJavaScriptException();
        return {};
    }

    uint64_t s = size.has_value() ? size.value().value : (desc_.size - offset);

    uint64_t start = offset;
    uint64_t end = offset + s;
    for (auto& mapping : mapped_) {
        if (mapping.Intersects(start, end)) {
            Errors::OperationError(env).ThrowAsJavaScriptException();
            return {};
        }
    }

    auto* ptr = (desc_.usage & wgpu::BufferUsage::MapWrite)
                    ? buffer_.GetMappedRange(offset, s)
                    : const_cast<void*>(buffer_.GetConstMappedRange(offset, s));
    if (!ptr) {
        Errors::OperationError(env).ThrowAsJavaScriptException();
        return {};
    }
    auto array_buffer = Napi::ArrayBuffer::New(env, ptr, s);
    // TODO(crbug.com/dawn/1135): Ownership here is the wrong way around.
    mapped_.emplace_back(Mapping{start, end, Napi::Persistent(array_buffer)});
    return array_buffer;
}

void GPUBuffer::unmap(Napi::Env env) {
    buffer_.Unmap();

    if (state_ != State::Destroyed && state_ != State::Unmapped) {
        DetachMappings();
        state_ = State::Unmapped;
    }
}

void GPUBuffer::destroy(Napi::Env) {
    if (state_ == State::Destroyed) {
        return;
    }

    if (state_ != State::Unmapped) {
        DetachMappings();
    }

    buffer_.Destroy();
    state_ = State::Destroyed;
}

interop::GPUSize64Out GPUBuffer::getSize(Napi::Env) {
    return buffer_.GetSize();
}

interop::GPUBufferMapState GPUBuffer::getMapState(Napi::Env env) {
    interop::GPUBufferMapState result;

    Converter conv(env);
    if (!conv(result, buffer_.GetMapState())) {
        Napi::Error::New(env, "Couldn't convert usage to a JavaScript value.")
            .ThrowAsJavaScriptException();
        return interop::GPUBufferMapState::kUnmapped;
    }

    return result;
}

interop::GPUFlagsConstant GPUBuffer::getUsage(Napi::Env env) {
    interop::GPUBufferUsageFlags result;

    Converter conv(env);
    if (!conv(result, buffer_.GetUsage())) {
        Napi::Error::New(env, "Couldn't convert usage to a JavaScript value.")
            .ThrowAsJavaScriptException();
        return 0u;  // Doesn't get used.
    }

    return result;
}

void GPUBuffer::DetachMappings() {
    for (auto& mapping : mapped_) {
        mapping.buffer.Value().Detach();
    }
    mapped_.clear();
}

std::string GPUBuffer::getLabel(Napi::Env) {
    return label_;
}

void GPUBuffer::setLabel(Napi::Env, std::string value) {
    buffer_.SetLabel(value.c_str());
    label_ = value;
}

}  // namespace wgpu::binding
