// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/wire/client/ShaderModule.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "absl/strings/str_format.h"
#include "partition_alloc/pointers/raw_ptr.h"
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/wire/client/Client.h"
#include "src/dawn/wire/client/Device.h"
#include "src/utils/compiler.h"

namespace dawn::wire::client {

// static
ShaderModule* ShaderModule::Create(Device* device, const ShaderModuleDescriptor* descriptor) {
    DAWN_ASSERT(descriptor != nullptr);

    Client* client = device->GetClient();
    Ref<ShaderModule> shaderModule = client->Make<ShaderModule>(device->GetInstance());

    ShaderModuleDescriptor desc = *descriptor;
    desc.nextInChain = nullptr;

    // In Dawn wire client, we replace ShaderSourceSPIRV extensions with DawnShaderSourceSPIRV
    // extensions. This requires us to potentially make a deep copy of the extensions to re-create
    // the chain, replacing any ShaderSourceSPIRVs along the way. When/if we run into duplicate or
    // invalid extensions, instead of trying to forward the descriptor to the server, we just ask
    // the server to create an error shader module instead.
    std::optional<DawnShaderSourceSPIRV> dawnShaderSourceSPIRV;
    std::optional<ShaderSourceWGSL> shaderSourceWGSL;
    std::optional<DawnShaderModuleSPIRVOptionsDescriptor> dawnShaderModuleSPIRVOptionsDescriptor;
    std::optional<ShaderModuleCompilationOptions> shaderModuleCompilationOptions;

    std::vector<ChainedStruct*> chainOrder;
    std::string errorMessage;
    for (const ChainedStruct* chain = descriptor->nextInChain; chain != nullptr;
         chain = chain->nextInChain) {
        switch (chain->sType) {
            case wgpu::SType::ShaderSourceSPIRV: {
                if (dawnShaderSourceSPIRV.has_value()) {
                    errorMessage = "Duplicate chained struct of type ShaderSourceSPIRV.";
                    break;
                }
                const auto* spirv = reinterpret_cast<const wgpu::ShaderSourceSPIRV*>(chain);
                DawnShaderSourceSPIRV dawnSpirv;
                // SAFETY: The application must ensure that `code` points at `codeSize` uint32_ts.
                DAWN_UNSAFE_BUFFERS(dawnSpirv.code = {spirv->code, spirv->codeSize});
                dawnShaderSourceSPIRV = dawnSpirv;
                chainOrder.push_back(&*dawnShaderSourceSPIRV);
                break;
            }
            case wgpu::SType::DawnShaderSourceSPIRV:
                if (dawnShaderSourceSPIRV.has_value()) {
                    errorMessage = "Duplicate chained struct of type DawnShaderSourceSPIRV.";
                    break;
                }
                dawnShaderSourceSPIRV = *reinterpret_cast<const DawnShaderSourceSPIRV*>(chain);
                chainOrder.push_back(&*dawnShaderSourceSPIRV);
                break;
            case wgpu::SType::ShaderSourceWGSL:
                if (shaderSourceWGSL.has_value()) {
                    errorMessage = "Duplicate chained struct of type ShaderSourceWGSL.";
                    break;
                }
                shaderSourceWGSL = *reinterpret_cast<const ShaderSourceWGSL*>(chain);
                chainOrder.push_back(&*shaderSourceWGSL);
                break;
            case wgpu::SType::DawnShaderModuleSPIRVOptionsDescriptor:
                if (dawnShaderModuleSPIRVOptionsDescriptor.has_value()) {
                    errorMessage =
                        "Duplicate chained struct of type DawnShaderModuleSPIRVOptionsDescriptor.";
                    break;
                }
                dawnShaderModuleSPIRVOptionsDescriptor =
                    *reinterpret_cast<const DawnShaderModuleSPIRVOptionsDescriptor*>(chain);
                chainOrder.push_back(&*dawnShaderModuleSPIRVOptionsDescriptor);
                break;
            case wgpu::SType::ShaderModuleCompilationOptions:
                if (shaderModuleCompilationOptions.has_value()) {
                    errorMessage =
                        "Duplicate chained struct of type ShaderModuleCompilationOptions.";
                    break;
                }
                shaderModuleCompilationOptions =
                    *reinterpret_cast<const ShaderModuleCompilationOptions*>(chain);
                chainOrder.push_back(&*shaderModuleCompilationOptions);
                break;
            default:
                errorMessage =
                    absl::StrFormat("Unsupported or invalid chained struct with SType (%u).",
                                    static_cast<uint32_t>(chain->sType));
                break;
        }
        if (!errorMessage.empty()) {
            break;
        }
    }

    if (!errorMessage.empty()) {
        DeviceCreateErrorShaderModuleCmd cmd;
        cmd.self = ToAPI(device);
        cmd.descriptor = ToWireCmd(&desc);
        cmd.errorMessage = ToOutputStringView(errorMessage);
        cmd.result = shaderModule->GetWireHandle(client);
        client->SerializeCommand(std::move(cmd));
        return ReturnToAPI2(std::move(shaderModule));
    }

    const ChainedStruct** last = &desc.nextInChain;
    for (ChainedStruct* current : chainOrder) {
        current->nextInChain = nullptr;
        *last = current;
        last = &current->nextInChain;
    }

    DeviceCreateShaderModuleCmd cmd;
    cmd.self = ToAPI(device);
    cmd.descriptor = ToWireCmd(&desc);
    cmd.result = shaderModule->GetWireHandle(client);
    client->SerializeCommand(std::move(cmd));
    return ReturnToAPI2(std::move(shaderModule));
}

class ShaderModule::CompilationInfoEvent final : public TrackedEvent {
  public:
    static constexpr EventType kType = EventType::CompilationInfo;

    CompilationInfoEvent(const WGPUCompilationInfoCallbackInfo& callbackInfo,
                         Ref<ShaderModule> shader)
        : TrackedEvent(callbackInfo.mode),
          mCallback(callbackInfo.callback),
          mUserdata1(callbackInfo.userdata1),
          mUserdata2(callbackInfo.userdata2),
          mShader(std::move(shader)) {
        DAWN_ASSERT(mShader != nullptr);
    }

    EventType GetType() override { return kType; }

    WireResult ReadyHook(FutureID futureId,
                         wgpu::CompilationInfoRequestStatus status,
                         const CompilationInfo* info) {
        if (mShader->mCompilationInfo) {
            // If we already cached the compilation info on the shader, we don't need to do it
            // again. This can happen if we were to call GetCompilationInfo multiple times before
            // the wire flushes.
            return ReadyHook(futureId);
        }

        mStatus = status;

        // Deep copy the CompilationInfo
        mShader->mMessageStrings.reserve(info->messages.size());
        mShader->mMessages.reserve(info->messages.size());
        mShader->mUtf16s.reserve(info->messages.size());
        for (size_t i = 0; i < info->messages.size(); i++) {
            DAWN_ASSERT(info->messages[i].length != WGPU_STRLEN);
            mShader->mMessageStrings.emplace_back(info->messages[i].message);
            mShader->mMessages.push_back(info->messages[i]);
            mShader->mMessages[i].message = StringView(mShader->mMessageStrings[i]);
            mShader->mMessages[i].nextInChain = nullptr;

            // Iterate the message chain for extensions that we want to handle.
            const ChainedStruct** tail = &mShader->mMessages[i].nextInChain;
            const ChainedStruct* chain = info->messages[i].nextInChain;
            // Guard against duplicates, to avoid a reallocation on the destination vector.
            // Duplicate structs of the same type are not valid in the first place, so don't
            // do much to try to recover or error out.
            bool seenDawnCompilationMessageUtf16 = false;
            while (chain != nullptr) {
                switch (chain->sType) {
                    case wgpu::SType::DawnCompilationMessageUtf16: {
                        if (!seenDawnCompilationMessageUtf16) {
                            seenDawnCompilationMessageUtf16 = true;
                            auto* next = &mShader->mUtf16s.emplace_back(
                                *reinterpret_cast<const DawnCompilationMessageUtf16*>(chain));
                            *tail = next;
                            tail = &next->nextInChain;
                        }
                        break;
                    }
                    default:
                        break;
                }

                chain = chain->nextInChain;
            }

            // Ensure that the tail is pointing to nothing else.
            *tail = nullptr;
        }
        mShader->mCompilationInfo = CompilationInfo{
            .nextInChain = nullptr,
            .messages = mShader->mMessages,
        };

        return WireResult::Success;
    }

    WireResult ReadyHook(FutureID futureId) {
        // We call this ReadyHook when we already have a cached compilation on the shader (usually
        // from a previous GetCompilationInfo call).
        DAWN_ASSERT(mShader->mCompilationInfo);
        mStatus = wgpu::CompilationInfoRequestStatus::Success;
        return WireResult::Success;
    }

  private:
    void CompleteImpl(FutureID futureID, EventCompletionType completionType) override {
        const WGPUCompilationInfo* compilationInfo = nullptr;
        if (completionType == EventCompletionType::Shutdown) {
            mStatus = wgpu::CompilationInfoRequestStatus::CallbackCancelled;
        } else {
            compilationInfo = ToAPI(&*mShader->mCompilationInfo);
        }

        void* userdata1 = mUserdata1.ExtractAsDangling();
        void* userdata2 = mUserdata2.ExtractAsDangling();
        if (mCallback) {
            mCallback(ToAPI(mStatus), compilationInfo, userdata1, userdata2);
        }
    }

    WGPUCompilationInfoCallback mCallback;
    raw_ptr<void> mUserdata1;
    raw_ptr<void> mUserdata2;

    wgpu::CompilationInfoRequestStatus mStatus = wgpu::CompilationInfoRequestStatus::Success;

    // Strong reference to the shader so that when we call the callback we can pass the
    // compilation info from `mShader`.
    Ref<ShaderModule> mShader;
};

ObjectType ShaderModule::GetObjectType() const {
    return ObjectType::ShaderModule;
}

Future ShaderModule::APIGetCompilationInfo(const WGPUCompilationInfoCallbackInfo& callbackInfo) {
    auto [futureIDInternal, tracked] =
        GetEventManager().TrackEvent(AcquireRef(new CompilationInfoEvent(callbackInfo, this)));
    if (!tracked) {
        return {futureIDInternal};
    }

    // If we already have a cached compilation info object, we can set it ready now.
    if (mCompilationInfo) {
        auto wireStatus = GetEventManager().SetFutureReady<CompilationInfoEvent>(futureIDInternal);
        DAWN_CHECK(wireStatus == WireResult::Success);
        return {futureIDInternal};
    }

    ShaderModuleGetCompilationInfoCmd cmd;
    cmd.shaderModuleId = GetWireHandle(GetClient()).id;
    cmd.instanceId = GetInstance()->GetWireHandle(GetClient()).id;
    cmd.future = {futureIDInternal};

    GetClient()->SerializeCommand(std::move(cmd));
    return {futureIDInternal};
}

WireResult Client::DoShaderModuleGetCompilationInfoCallback(
    ObjectId instanceId,
    Future future,
    wgpu::CompilationInfoRequestStatus status,
    const CompilationInfo* info) {
    return SetFutureReady<ShaderModule::CompilationInfoEvent>(instanceId, future.id, status, info);
}

}  // namespace dawn::wire::client
