// 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 <filesystem>
#include <iostream>
#include <utility>
#include <vector>

#include "src/tint/cmd/bench/bench.h"

#if TINT_BUILD_SPV_READER
#include "src/tint/lang/spirv/reader/reader.h"
#endif

#if TINT_BUILD_WGSL_WRITER
#include "src/tint/lang/wgsl/writer/writer.h"
#endif

#if TINT_BUILD_WGSL_READER
#include "src/tint/lang/wgsl/reader/reader.h"
#endif

#include "src/tint/utils/text/string.h"
#include "src/tint/utils/text/string_stream.h"

namespace tint::bench {
namespace {

std::filesystem::path kInputFileDir;

/// Copies the content from the file named `input_file` to `buffer`,
/// assuming each element in the file is of type `T`.  If any error occurs,
/// writes error messages to the standard error stream and returns false.
/// Assumes the size of a `T` object is divisible by its required alignment.
/// @returns true if we successfully read the file.
template <typename T>
Result<std::vector<T>> ReadFile(const std::string& input_file) {
    FILE* file = nullptr;
#if defined(_MSC_VER)
    fopen_s(&file, input_file.c_str(), "rb");
#else
    file = fopen(input_file.c_str(), "rb");
#endif
    if (!file) {
        return Failure{"Failed to open " + input_file};
    }

    fseek(file, 0, SEEK_END);
    const auto file_size = static_cast<size_t>(ftell(file));
    if (0 != (file_size % sizeof(T))) {
        StringStream err;
        err << "File " << input_file
            << " does not contain an integral number of objects: " << file_size
            << " bytes in the file, require " << sizeof(T) << " bytes per object";
        fclose(file);
        return Failure{err.str()};
    }
    fseek(file, 0, SEEK_SET);

    std::vector<T> buffer;
    buffer.resize(file_size / sizeof(T));

    size_t bytes_read = fread(buffer.data(), 1, file_size, file);
    fclose(file);
    if (bytes_read != file_size) {
        return Failure{"Failed to read " + input_file};
    }

    return buffer;
}

bool FindBenchmarkInputDir() {
    // Attempt to find the benchmark input files by searching up from the current
    // working directory.
    auto path = std::filesystem::current_path();
    while (std::filesystem::is_directory(path)) {
        auto test = path / "test" / "tint" / "benchmark";
        if (std::filesystem::is_directory(test)) {
            kInputFileDir = test;
            return true;
        }
        auto parent = path.parent_path();
        if (path == parent) {
            break;
        }
        path = parent;
    }
    return false;
}

}  // namespace

bool Initialize() {
    if (!FindBenchmarkInputDir()) {
        std::cerr << "failed to locate benchmark input files\n";
        return false;
    }
    return true;
}

Result<Source::File> LoadInputFile(std::string name) {
    auto path = std::filesystem::path(name).is_absolute() ? name : (kInputFileDir / name).string();
    if (tint::HasSuffix(path, ".wgsl")) {
#if TINT_BUILD_WGSL_READER
        auto data = ReadFile<uint8_t>(path);
        if (data != Success) {
            return data.Failure();
        }
        return tint::Source::File(path, std::string(data->begin(), data->end()));
#else
        return Failure{"cannot load " + path + " file as TINT_BUILD_WGSL_READER is not enabled"};
#endif
    }
    if (tint::HasSuffix(path, ".spv")) {
#if !TINT_BUILD_SPV_READER
        return Failure{"cannot load " + path + " as TINT_BUILD_SPV_READER is not enabled"};
#elif !TINT_BUILD_WGSL_WRITER
        return Failure{"cannot load " + path + " as TINT_BUILD_WGSL_WRITER is not enabled"};
#else

        auto spirv = ReadFile<uint32_t>(path);
        if (spirv == Success) {
            tint::spirv::reader::Options spirv_opts;
            spirv_opts.allow_non_uniform_derivatives = true;
            auto program = tint::spirv::reader::Read(spirv.Get(), spirv_opts);
            if (!program.IsValid()) {
                return Failure{program.Diagnostics()};
            }
            auto result = tint::wgsl::writer::Generate(program, {});
            if (result != Success) {
                return result.Failure();
            }
            return tint::Source::File(path, result->wgsl);
        }
        return spirv.Failure();
#endif
    }
    return Failure{"unsupported file extension: '" + name + "'"};
}

Result<ProgramAndFile> LoadProgram(std::string name) {
    auto res = bench::LoadInputFile(name);
    if (res != Success) {
        return res.Failure();
    }
    auto file = std::make_unique<Source::File>(res.Get());
    auto program = wgsl::reader::Parse(file.get());
    if (!program.IsValid()) {
        return Failure{program.Diagnostics()};
    }
    return ProgramAndFile{std::move(program), std::move(file)};
}

}  // namespace tint::bench
