// 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 "dawn/native/CompilationMessages.h"

#include <utility>

#include "dawn/common/Assert.h"
#include "dawn/common/StringViewUtils.h"
#include "dawn/native/dawn_platform.h"
#include "tint/tint.h"

namespace dawn::native {

namespace {

wgpu::CompilationMessageType TintSeverityToMessageType(tint::diag::Severity severity) {
    switch (severity) {
        case tint::diag::Severity::Note:
            return wgpu::CompilationMessageType::Info;
        case tint::diag::Severity::Warning:
            return wgpu::CompilationMessageType::Warning;
        default:
            return wgpu::CompilationMessageType::Error;
    }
}

}  // anonymous namespace

uint64_t CountUTF16CodeUnitsFromUTF8String(const std::string_view& utf8String) {
    if (tint::utf8::IsASCII(utf8String)) {
        return utf8String.size();
    }

    uint64_t numberOfUTF16CodeUnits = 0;
    std::string_view remaining = utf8String;
    while (!remaining.empty()) {
        auto [codePoint, utf8CharacterByteLength] = tint::utf8::Decode(remaining);
        // WGSL validation will already have prevented invalid UTF-8.
        DAWN_ASSERT(utf8CharacterByteLength != 0);
        remaining = remaining.substr(utf8CharacterByteLength);

        // Count the number of code units in UTF-16. See https://en.wikipedia.org/wiki/UTF-16 for
        // more details. Note that while the code points ranging from U+D800 to U+DFFF are not
        // encodable in UTF-16 (they are surrogate code points), we still mark them as needing a
        // single UTF-16 code unit. The computations performed in this function are only useful when
        // the application uses UTF-16 internally (like JS code), so the source would have been
        // valid UTF-16 already.
        if (codePoint.value <= 0xFFFF) {
            // Code points from U+0000 to U+D7FF and U+E000 to U+FFFF are encoded as single 16-bit
            // code units. As noted above we also count surrogates as one UTF-16 code unit.
            numberOfUTF16CodeUnits += 1;
        } else {
            // Code points from U+010000 to U+10FFFF are encoded as two 16-bit code units.
            numberOfUTF16CodeUnits += 2;
        }
    }

    return numberOfUTF16CodeUnits;
}

void ParsedCompilationMessages::AddUnanchoredMessage(std::string_view message,
                                                     wgpu::CompilationMessageType type) {
    CompilationMessageContent m = {};
    m.message = message;
    m.type = type;
    AddMessage(std::move(m));
}

void ParsedCompilationMessages::AddMessageForTesting(std::string_view message,
                                                     wgpu::CompilationMessageType type,
                                                     uint64_t lineNum,
                                                     uint64_t linePos,
                                                     uint64_t offset,
                                                     uint64_t length) {
    AddMessage({{
        .message = std::string(message),
        .type = type,
        .lineNum = lineNum,
        .linePosInBytes = linePos,
        .offsetInBytes = offset,
        .lengthInBytes = length,
        // Incorrect for non-ACSII strings
        .linePosInUTF16 = linePos,
        .offsetInUTF16 = offset,
        .lengthInUTF16 = length,
    }});
}

void ParsedCompilationMessages::AddMessage(const tint::diag::Diagnostic& diagnostic) {
    // Tint line and column values are 1-based.
    uint64_t lineNum = diagnostic.source.range.begin.line;
    uint64_t linePosInBytes = diagnostic.source.range.begin.column;
    // The offset is 0-based.
    uint64_t offsetInBytes = 0;
    uint64_t lengthInBytes = 0;
    uint64_t linePosInUTF16 = 0;
    uint64_t offsetInUTF16 = 0;
    uint64_t lengthInUTF16 = 0;

    if (lineNum && linePosInBytes && diagnostic.source.file) {
        const tint::Source::FileContent& content = diagnostic.source.file->content;

        // Tint stores line as std::string_view in a complete source std::string that's in the
        // source file. So to get the offset in bytes of a line we just need to substract its start
        // pointer with the start of the file's content. Note that line numbering in Tint source
        // range starts at 1 while the array of lines start at 0 (hence the -1).
        const char* fileStart = content.data.data();
        const char* lineStart = content.lines[lineNum - 1].data();
        offsetInBytes = static_cast<uint64_t>(lineStart - fileStart) + linePosInBytes - 1;

        // The linePosInBytes is 1-based.
        uint64_t linePosOffsetInUTF16 =
            CountUTF16CodeUnitsFromUTF8String(std::string_view(lineStart, linePosInBytes - 1));
        linePosInUTF16 = linePosOffsetInUTF16 + 1;

        // The offset is 0-based.
        uint64_t lineStartToFileStartOffsetInUTF16 = CountUTF16CodeUnitsFromUTF8String(
            std::string_view(fileStart, static_cast<uint64_t>(lineStart - fileStart)));
        offsetInUTF16 = lineStartToFileStartOffsetInUTF16 + linePosInUTF16 - 1;

        // If the range has a valid start but the end is not specified, clamp it to the start.
        uint64_t endLineNum = diagnostic.source.range.end.line;
        uint64_t endLineCol = diagnostic.source.range.end.column;
        if (endLineNum == 0 || endLineCol == 0) {
            endLineNum = lineNum;
            endLineCol = linePosInBytes;
        }

        const char* endLineStart = content.lines[endLineNum - 1].data();
        uint64_t endOffsetInBytes =
            static_cast<uint64_t>(endLineStart - fileStart) + endLineCol - 1;
        // The length of the message is the difference between the starting offset and the
        // ending offset. Negative ranges aren't allowed.
        DAWN_ASSERT(endOffsetInBytes >= offsetInBytes);
        lengthInBytes = endOffsetInBytes - offsetInBytes;
        lengthInUTF16 = CountUTF16CodeUnitsFromUTF8String(
            std::string_view(fileStart + offsetInBytes, lengthInBytes));
    }

    std::string plainMessage = diagnostic.message.Plain();

    AddMessage({{
        .message = plainMessage,
        .type = TintSeverityToMessageType(diagnostic.severity),
        .lineNum = lineNum,
        .linePosInBytes = linePosInBytes,
        .offsetInBytes = offsetInBytes,
        .lengthInBytes = lengthInBytes,
        .linePosInUTF16 = linePosInUTF16,
        .offsetInUTF16 = offsetInUTF16,
        .lengthInUTF16 = lengthInUTF16,
    }});
}

void ParsedCompilationMessages::AddMessage(CompilationMessageContent&& message) {
    messages.push_back(message);
}

void ParsedCompilationMessages::AddMessages(const tint::diag::List& diagnostics) {
    for (const auto& diag : diagnostics) {
        AddMessage(diag);
    }

    AddFormattedTintMessages(diagnostics);
}

void ParsedCompilationMessages::AddFormattedTintMessages(const tint::diag::List& diagnostics) {
    tint::diag::List messageList;
    size_t warningCount = 0;
    size_t errorCount = 0;
    for (auto& diag : diagnostics) {
        switch (diag.severity) {
            case tint::diag::Severity::Error: {
                errorCount++;
                messageList.Add(diag);
                break;
            }
            case tint::diag::Severity::Warning: {
                warningCount++;
                messageList.Add(diag);
                break;
            }
            case tint::diag::Severity::Note: {
                messageList.Add(diag);
                break;
            }
            default:
                break;
        }
    }
    if (errorCount == 0 && warningCount == 0) {
        return;
    }
    tint::diag::Formatter::Style style;
    style.print_newline_at_end = false;
    std::ostringstream t;
    if (errorCount > 0) {
        t << errorCount << " error(s) ";
        if (warningCount > 0) {
            t << "and ";
        }
    }
    if (warningCount > 0) {
        t << warningCount << " warning(s) ";
    }
    t << "generated while compiling the shader:\n"
      << tint::diag::Formatter{style}.Format(messageList).Plain();
    formattedTintMessages.push_back(t.str());
}

OwnedCompilationMessages::OwnedCompilationMessages(
    ParsedCompilationMessages&& parsedCompilationMessagges)
    : mMessageContents(parsedCompilationMessagges), mCompilationInfo() {
    // Reserve the size of messages to avoid reallocations, so that we can use
    // the raw pointer when adding each message.
    mMessagesList.reserve(mMessageContents.messages.size());
    mUtf16Messages.reserve(mMessageContents.messages.size());

    // Build the CompilationMessage and DawnCompilationMessageUtf16 object for each message.
    for (auto& m : mMessageContents.messages) {
        if (m.type == wgpu::CompilationMessageType::Error ||
            m.type == wgpu::CompilationMessageType::Warning) {
            mHasWarningsOrErrors = true;
        }

        DawnCompilationMessageUtf16& utf16 = mUtf16Messages.emplace_back();
        utf16.linePos = m.linePosInUTF16;
        utf16.offset = m.offsetInUTF16;
        utf16.length = m.lengthInUTF16;

        CompilationMessage& message = mMessagesList.emplace_back();
        message.message = ToOutputStringView(m.message);
        message.type = m.type;
        message.lineNum = m.lineNum;
        message.linePos = m.linePosInBytes;
        message.offset = m.offsetInBytes;
        message.length = m.lengthInBytes;
        // Points to the created DawnCompilationMessageUtf16, pointers would keep valid since
        // mUtf16Messages has been reserved to the size of messages.
        message.nextInChain = &utf16;
    }

    mCompilationInfo.messageCount = mMessagesList.size();
    mCompilationInfo.messages = mMessagesList.data();
}

const CompilationInfo* OwnedCompilationMessages::GetCompilationInfo() const {
    return &mCompilationInfo;
}

const std::vector<std::string>& OwnedCompilationMessages::GetFormattedTintMessages() const {
    return mMessageContents.formattedTintMessages;
}

bool OwnedCompilationMessages::HasWarningsOrErrors() const {
    return mHasWarningsOrErrors;
}

}  // namespace dawn::native
