/*
 * Fooyin
 * Copyright © 2024, Luke Taylor <luket@pm.me>
 *
 * Fooyin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fooyin is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Fooyin.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include <QColor>
#include <QFont>
#include <QVariant>

#include <cstdint>

namespace Fooyin {
enum class RichAlignment : uint8_t
{
    Left = 0,
    Right,
};

struct RichColour
{
    enum class Type : uint8_t
    {
        Default = 0,
        Explicit,
    };

    Type type{Type::Default};
    QColor colour;
    int alpha{-1};

    [[nodiscard]] bool isExplicit() const
    {
        return type == Type::Explicit && colour.isValid();
    }

    void setColour(const QColor& newColour)
    {
        type   = Type::Explicit;
        colour = newColour;
    }

    bool operator==(const RichColour& other) const = default;
};

struct RichFormatting
{
    QFont font;
    RichColour colour;
    QString link;
    RichAlignment alignment{RichAlignment::Left};

    bool operator==(const RichFormatting& other) const
    {
        return std::tie(font, colour, link, alignment)
            == std::tie(other.font, other.colour, other.link, other.alignment);
    };
};

struct RichTextBlock
{
    QString text;
    RichFormatting format;

    bool operator==(const RichTextBlock& other) const
    {
        return std::tie(text, format) == std::tie(other.text, other.format);
    };
};

struct RichText
{
    std::vector<RichTextBlock> blocks;

    bool operator==(const RichText& other) const
    {
        return blocks == other.blocks;
    };

    operator QVariant() const
    {
        return QVariant::fromValue(*this);
    }

    [[nodiscard]] size_t size() const
    {
        return blocks.size();
    }

    [[nodiscard]] bool empty() const
    {
        return blocks.empty();
    }

    void clear()
    {
        blocks.clear();
    }

    [[nodiscard]] QString joinedText() const
    {
        QString text;
        for(const auto& block : blocks) {
            text.append(block.text);
        }
        return text;
    }
};

struct RichScript
{
    QString script;
    RichText text;

    bool operator==(const RichScript& other) const
    {
        return std::tie(script, text) == std::tie(other.script, other.text);
    };

    friend QDataStream& operator<<(QDataStream& stream, const RichScript& richScript)
    {
        stream << richScript.script;
        return stream;
    }

    friend QDataStream& operator>>(QDataStream& stream, RichScript& richScript)
    {
        stream >> richScript.script;
        return stream;
    }
};
} // namespace Fooyin
