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

// GEN_BUILD:CONDITION(tint_build_is_linux || tint_build_is_mac)

#include <unistd.h>

#include <sys/select.h>
#include <termios.h>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <optional>
#include <string_view>
#include <utility>

#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/system/env.h"
#include "src/tint/utils/system/terminal.h"

namespace tint {
namespace {

std::optional<bool> TerminalIsDarkImpl(FILE* out) {
    // Check the terminal can be queried, and supports colors.
    if (!isatty(STDIN_FILENO) || !TerminalSupportsColors(out)) {
        return std::nullopt;
    }

    // Get the file descriptor for 'out'
    int out_fd = fileno(out);
    if (out_fd == -1) {
        return std::nullopt;
    }

    // Store the current attributes for 'out', restore it before returning
    termios original_state{};
    if (tcgetattr(out_fd, &original_state) != 0) {
        return std::nullopt;
    }
    TINT_DEFER(tcsetattr(out_fd, TCSADRAIN, &original_state));

    // Prevent echoing.
    termios state = original_state;
    state.c_lflag &= ~static_cast<tcflag_t>(ECHO | ICANON);
    if (tcsetattr(out_fd, TCSADRAIN, &state) != 0) {
        return std::nullopt;
    }

    // Emit the device control escape sequence to query the terminal colors.
    static constexpr std::string_view kQuery = "\033]11;?\033\\";
    fwrite(kQuery.data(), 1, kQuery.length(), out);
    fflush(out);

    // Timeout for attempting to read the response.
    static constexpr auto kTimeout = std::chrono::milliseconds(300);

    // Record the start time.
    auto start = std::chrono::steady_clock::now();

    // Returns true if there's data available on stdin, or false if no data was available after
    // 100ms.
    auto poll_stdin = [] {
        // Note: These macros introduce identifiers that start with `__`.
        TINT_BEGIN_DISABLE_WARNING(RESERVED_IDENTIFIER);
        fd_set rfds{};
        FD_ZERO(&rfds);
        FD_SET(STDIN_FILENO, &rfds);
        timeval tv{};
        tv.tv_sec = 0;
        tv.tv_usec = 100'000;
        int res = select(STDIN_FILENO + 1, &rfds, nullptr, nullptr, &tv);
        return res > 0 && FD_ISSET(STDIN_FILENO, &rfds);
        TINT_END_DISABLE_WARNING(RESERVED_IDENTIFIER);
    };

    // Helpers for parsing the response.
    Vector<char, 8> peek;
    auto read = [&]() -> std::optional<char> {
        if (!peek.IsEmpty()) {
            return peek.Pop();
        }
        while ((std::chrono::steady_clock::now() - start) < kTimeout) {
            if (!poll_stdin()) {
                return std::nullopt;
            }

            char c;
            if (fread(&c, 1, 1, stdin) == 1) {
                return c;
            }
        }
        return std::nullopt;
    };

    auto match = [&](std::string_view str) {
        for (size_t i = 0; i < str.length(); i++) {
            auto c = read();
            if (c != str[i]) {
                if (c) {
                    peek.Push(*c);
                }
                while (i != 0) {
                    peek.Push(str[--i]);
                }
                return false;
            }
        }
        return true;
    };

    struct Hex {
        uint32_t num = 0;  // The parsed hex number
        uint32_t len = 0;  // Number of hex digits parsed
    };
    auto hex = [&] {
        uint32_t num = 0;
        uint32_t len = 0;
        while (auto c = read()) {
            if (c >= '0' && c <= '9') {
                num = num * 16 + static_cast<uint32_t>(*c - '0');
                len++;
            } else if (c >= 'a' && c <= 'z') {
                num = num * 16 + 10 + static_cast<uint32_t>(*c - 'a');
                len++;
            } else if (c >= 'A' && c <= 'Z') {
                num = num * 16 + 10 + static_cast<uint32_t>(*c - 'A');
                len++;
            } else {
                peek.Push(*c);
                break;
            }
        }
        return Hex{num, len};
    };

    if (!match("\033]11;rgb:")) {
        return std::nullopt;
    }

    auto r_i = hex();
    if (!match("/")) {
        return std::nullopt;
    }
    auto g_i = hex();
    if (!match("/")) {
        return std::nullopt;
    }
    auto b_i = hex();

    if (r_i.len != g_i.len || g_i.len != b_i.len) {
        return std::nullopt;
    }

    uint32_t max = 0;
    switch (r_i.len) {
        case 2:  // rr/gg/bb
            max = 0xff;
            break;
        case 4:  // rrrr/gggg/bbbb
            max = 0xffff;
            break;
        default:
            return std::nullopt;
    }

    if (!match("\x07") && !match("\x1b")) {
        return std::nullopt;
    }

    // https://en.wikipedia.org/wiki/Relative_luminance
    float r = static_cast<float>(r_i.num) / static_cast<float>(max);
    float g = static_cast<float>(g_i.num) / static_cast<float>(max);
    float b = static_cast<float>(b_i.num) / static_cast<float>(max);
    return (0.2126f * r + 0.7152f * g + 0.0722f * b) < 0.5f;
}

}  // namespace

bool TerminalSupportsColors(FILE* f) {
    if (!isatty(fileno(f))) {
        return false;
    }

    if (auto term = GetEnvVar("TERM"); !term.empty()) {
        return term == "cygwin" || term == "linux" || term == "rxvt-unicode-256color" ||
               term == "rxvt-unicode" || term == "screen-256color" || term == "screen" ||
               term == "tmux-256color" || term == "tmux" || term == "xterm-256color" ||
               term == "xterm-color" || term == "xterm";
    }

    return false;
}

/// Probes the terminal using a Device Control escape sequence to get the background color.
/// @see https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Device-Control-functions
std::optional<bool> TerminalIsDark(FILE* out) {
    static std::optional<bool> result = TerminalIsDarkImpl(out);
    return result;
}

}  // namespace tint
