/* SPDX-License-Identifier: GPL-3.0-or-later
 * SPDX-FileCopyrightText: 2024-2026 Soren Stoutner <soren@stoutner.com>
 *
 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc/>.
 *
 * This program 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.
 *
 * This program 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
 * this program.  If not, see <https://www.gnu.org/licenses/>.
 */

// Application headers.
#include "UrlLineEdit.h"

// Qt toolkit headers.
#include <QInputMethodEvent>

// Construct the class.
UrlLineEdit::UrlLineEdit(QWidget *parentWidgetPointer) : KLineEdit(parentWidgetPointer) {}

void UrlLineEdit::focusInEvent(QFocusEvent *focusEventPointer)
{
    // Create an input method event attribute list.
    QList<QInputMethodEvent::Attribute> inputMethodEventAttributeList;

    // Create an input method event with no formatting.
    QInputMethodEvent inputMethodEvent(QString(QLatin1String("")), inputMethodEventAttributeList);

    // Apply the empty formatting to remove the URL highlighting.
    event(&inputMethodEvent);

    // Run the default commands.
    KLineEdit::focusInEvent(focusEventPointer);
}

void UrlLineEdit::focusOutEvent(QFocusEvent *focusEventPointer)
{
    // Reapply the highlight to the current text.
    setText(text());

    // Run the default commands.
    KLineEdit::focusOutEvent(focusEventPointer);
}

void UrlLineEdit::setText(const QString &urlString)
{
    // Wipe the currently displayed text.
    KLineEdit::setText(QLatin1String(""));

    // Only highlight the URL if it starts with a known schema.
    if (urlString.startsWith(QLatin1String("https://")) || urlString.startsWith(QLatin1String("http://")) || urlString.startsWith(QLatin1String("view-source:")))
    {
        // Create an input method event attribute list.
        QList<QInputMethodEvent::Attribute> inputMethodEventAttributeList;

        // Calculate the URL string length.
        int urlStringLength = urlString.length();

        // Get the index of end of the schema.
        int endOfSchemaIndex = urlString.indexOf(QLatin1String("//")) + 2;

        // Get the index of the `/` immediately after the domain name.  If this doesn't exit it will be set to `-1`.
        int endOfDomainNameIndex = urlString.indexOf(QLatin1Char('/'), endOfSchemaIndex);

        // Get the index of the last `.` in the domain.
        int lastDotIndex = urlString.lastIndexOf(QLatin1Char('.'), endOfDomainNameIndex - urlStringLength);

        // Get the index of the penultimate `.` in the domain.  If this doesn't exist it will be set to `-1`.
        int penultimateDotIndex = urlString.lastIndexOf(QLatin1Char('.'), lastDotIndex - urlStringLength - 1);

        // Create the text character formats.
        QTextCharFormat grayTextCharFormat;
        QTextCharFormat schemaTextCharFormat;

        // Set the text character format colors.
        grayTextCharFormat.setForeground(Qt::darkGray);

        // Set the schema text character format color.
        if (urlString.startsWith(QLatin1String("http://")) || urlString.startsWith(QLatin1String("view-source:http://")))
            schemaTextCharFormat.setForeground(Qt::red);
        else
            schemaTextCharFormat = grayTextCharFormat;

        // Append the schema text format format.
        inputMethodEventAttributeList.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, endOfSchemaIndex, schemaTextCharFormat));

        // Append the subdomain format if the subdomain exists.  If it doesn't, the penultimate dot index will be `-1`.
        if (penultimateDotIndex > 0)
            inputMethodEventAttributeList.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, endOfSchemaIndex, penultimateDotIndex + 1 - endOfSchemaIndex, grayTextCharFormat));

        // Append the post domain formatting if text exists after the domain name.  If it doesn't, the end of domain name index will be `-1`.
        if (endOfDomainNameIndex > 0)
            inputMethodEventAttributeList.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, endOfDomainNameIndex, urlStringLength - endOfDomainNameIndex, grayTextCharFormat));

        // Create an input method event with an empty pre-edit string.
        QInputMethodEvent inputMethodEvent(QLatin1String(""), inputMethodEventAttributeList);

        // Apply the URL highlighting.
        event(&inputMethodEvent);
    }
    else  // Reset the URL highlighting.
    {
        // Create an empty input method event attribute list.
        QList<QInputMethodEvent::Attribute> inputMethodEventAttributeList;

        // Create an input method event with an empty pre-edit string.
        QInputMethodEvent inputMethodEvent(QLatin1String(""), inputMethodEventAttributeList);

        // Apply the empty URL highlighting.
        event(&inputMethodEvent);

    }

    // Run the default commands.
    KLineEdit::setText(urlString);
}
