// Copyright 2023 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/node/binding/GPUAdapterInfo.h"

#include <cctype>
#include <iomanip>
#include <span>
#include <sstream>

#include "src/dawn/node/binding/Converter.h"
#include "src/utils/assert.h"
#include "src/utils/compiler.h"

namespace wgpu::binding {

////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPUAdapterInfo
////////////////////////////////////////////////////////////////////////////////

namespace {

interop::GPUSubgroupMatrixComponentType SubgroupMatrixComponentType(
    wgpu::SubgroupMatrixComponentType c) {
    switch (c) {
        case SubgroupMatrixComponentType::F32:
            return interop::GPUSubgroupMatrixComponentType::kF32;
        case SubgroupMatrixComponentType::F16:
            return interop::GPUSubgroupMatrixComponentType::kF16;
        case SubgroupMatrixComponentType::U32:
            return interop::GPUSubgroupMatrixComponentType::kU32;
        case SubgroupMatrixComponentType::I32:
            return interop::GPUSubgroupMatrixComponentType::kI32;
        case SubgroupMatrixComponentType::U8:
            return interop::GPUSubgroupMatrixComponentType::kU8;
        case SubgroupMatrixComponentType::I8:
            return interop::GPUSubgroupMatrixComponentType::kI8;
    }
    DAWN_ASSERT(false);
    return interop::GPUSubgroupMatrixComponentType::kF32;
}

struct GPUSubgroupMatrixConfig : public interop::GPUSubgroupMatrixConfig {
    interop::GPUSubgroupMatrixComponentType componentType;
    interop::GPUSubgroupMatrixComponentType resultComponentType;
    uint32_t M;
    uint32_t N;
    uint32_t K;

    explicit GPUSubgroupMatrixConfig(const wgpu::SubgroupMatrixConfig& config)
        : componentType(SubgroupMatrixComponentType(config.componentType)),
          resultComponentType(SubgroupMatrixComponentType(config.resultComponentType)),
          M(config.M),
          N(config.N),
          K(config.K) {}

    interop::GPUSubgroupMatrixComponentType getComponentType(Napi::Env) override {
        return componentType;
    }
    interop::GPUSubgroupMatrixComponentType getResultComponentType(Napi::Env) override {
        return resultComponentType;
    }
    uint32_t getM(Napi::Env) override { return M; }
    uint32_t getN(Napi::Env) override { return N; }
    uint32_t getK(Napi::Env) override { return K; }
};

// Normalize according to https://gpuweb.github.io/gpuweb/#normalized-identifier-string
std::string NormalizeIdentifierString(wgpu::StringView s) {
    std::ostringstream o;

    // Used to concatenate multiple non-alnum into a single dash.
    bool lastWasDash = false;
    // Used to start adding dashes only after we had one alnum.
    bool hadAlnum = false;

    for (char c : std::string_view(s)) {
        if (std::isalnum(c)) {
            o << static_cast<char>(std::tolower(c));
            lastWasDash = false;
            hadAlnum = true;
        } else if (!lastWasDash && hadAlnum) {
            o << '-';
            lastWasDash = true;
        }
    }

    return o.str();
}

}  // namespace

GPUAdapterInfo::GPUAdapterInfo(const wgpu::AdapterInfo& info)
    : vendor_(NormalizeIdentifierString(info.vendor)),
      architecture_(NormalizeIdentifierString(info.architecture)),
      device_(NormalizeIdentifierString(info.device)),
      description_(info.description),
      subgroup_min_size_(info.subgroupMinSize),
      subgroup_max_size_(info.subgroupMaxSize),
      is_fallback_adapter_(info.adapterType == wgpu::AdapterType::CPU) {
    auto* next = info.nextInChain;
    while (next) {
        if (next->sType == SType::AdapterPropertiesSubgroupMatrixConfigs) {
            auto* configs = static_cast<wgpu::AdapterPropertiesSubgroupMatrixConfigs*>(next);
            auto matrix_configs = WGPU_SPAN(configs->config);
            subgroup_matrix_configs_.reserve(matrix_configs.size());
            for (const auto& config : matrix_configs) {
                subgroup_matrix_configs_.push_back(config);
            }
        }
        next = next->nextInChain;
    }
}

std::string GPUAdapterInfo::getVendor(Napi::Env) {
    return vendor_;
}

std::string GPUAdapterInfo::getArchitecture(Napi::Env) {
    return architecture_;
}

std::string GPUAdapterInfo::getDevice(Napi::Env) {
    return device_;
}

std::string GPUAdapterInfo::getDescription(Napi::Env) {
    return description_;
}

uint32_t GPUAdapterInfo::getSubgroupMinSize(Napi::Env) {
    return subgroup_min_size_;
}

uint32_t GPUAdapterInfo::getSubgroupMaxSize(Napi::Env) {
    return subgroup_max_size_;
}

bool GPUAdapterInfo::getIsFallbackAdapter(Napi::Env) {
    return is_fallback_adapter_;
}

GPUAdapterInfo::SubgroupMatrixConfigs GPUAdapterInfo::getSubgroupMatrixConfigs(Napi::Env env) {
    SubgroupMatrixConfigs out;
    out.reserve(subgroup_matrix_configs_.size());
    for (auto& config : subgroup_matrix_configs_) {
        out.emplace_back(
            interop::GPUSubgroupMatrixConfig::Create<GPUSubgroupMatrixConfig>(env, config));
    }
    return out;
}

}  // namespace wgpu::binding
