/*  This file is part of the KDE libraries and the Kate part.
 *
 *  Copyright (C) 2014 Milian Wolff <mail@milianw.de>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

#include "katedefaultcolors.h"
#include "kateglobal.h"

#include <KColorUtils>

using namespace Kate;

KateDefaultColors::KateDefaultColors()
    /**
     * for unit testing: avoid global configs!
     */
    : m_view(QPalette::Active,
             KColorScheme::View,
             KSharedConfig::openConfig(KTextEditor::EditorPrivate::unitTestMode() ? QStringLiteral("unittestmoderc") : QString(), KTextEditor::EditorPrivate::unitTestMode() ? KConfig::SimpleConfig : KConfig::FullConfig))
    , m_window(QPalette::Active,
               KColorScheme::Window,
               KSharedConfig::openConfig(KTextEditor::EditorPrivate::unitTestMode() ? QStringLiteral("unittestmoderc") : QString(), KTextEditor::EditorPrivate::unitTestMode() ? KConfig::SimpleConfig : KConfig::FullConfig))
    , m_selection(QPalette::Active,
                  KColorScheme::Selection,
                  KSharedConfig::openConfig(KTextEditor::EditorPrivate::unitTestMode() ? QStringLiteral("unittestmoderc") : QString(), KTextEditor::EditorPrivate::unitTestMode() ? KConfig::SimpleConfig : KConfig::FullConfig))
    , m_inactiveSelection(QPalette::Inactive,
                          KColorScheme::Selection,
                          KSharedConfig::openConfig(KTextEditor::EditorPrivate::unitTestMode() ? QStringLiteral("unittestmoderc") : QString(), KTextEditor::EditorPrivate::unitTestMode() ? KConfig::SimpleConfig : KConfig::FullConfig))

    /**
     * init our colors
     */
    , m_background(m_view.background().color())
    , m_foreground(m_view.foreground().color())
    , m_backgroundLuma(KColorUtils::luma(m_background))
    , m_foregroundLuma(KColorUtils::luma(m_foreground))
{
}

QColor KateDefaultColors::color(ColorRole role) const
{
    switch (role) {
        case Background:
            return m_background;
        case SelectionBackground:
            return m_selection.background().color();
        case HighlightedLineBackground:
            return m_view.background(KColorScheme::AlternateBackground).color();
        case HighlightedBracket:
            return KColorUtils::tint(m_background, m_view.decoration(KColorScheme::HoverColor).color());
        case WordWrapMarker:
            return KColorUtils::shade(m_background, m_backgroundLuma > 0.3 ? -0.15 : 0.03);
        case TabMarker:
            return KColorUtils::shade(m_background, m_backgroundLuma > 0.7 ? -0.35 : 0.3);
        case IndentationLine:
            return KColorUtils::shade(m_background, m_backgroundLuma > 0.7 ? -0.35 : 0.3);
        case IconBar:
            return m_window.background().color();
        case CodeFolding:
            return m_inactiveSelection.background().color();
        case LineNumber:
        case CurrentLineNumber:
            return m_window.foreground().color();
        case Separator:
            return m_view.foreground(KColorScheme::InactiveText).color();
        case SpellingMistakeLine:
            return m_view.foreground(KColorScheme::NegativeText).color();
        case ModifiedLine:
            return m_view.background(KColorScheme::NegativeBackground).color();
        case SavedLine:
            return m_view.background(KColorScheme::PositiveBackground).color();
        case SearchHighlight:
            return adaptToScheme(Qt::yellow, BackgroundColor);
        case ReplaceHighlight:
            return adaptToScheme(Qt::green, BackgroundColor);
        case TemplateBackground:
            return m_window.background().color();
        case TemplateFocusedEditablePlaceholder:
            return m_view.background(KColorScheme::PositiveBackground).color();
        case TemplateEditablePlaceholder:
            return m_view.background(KColorScheme::PositiveBackground).color();
        case TemplateNotEditablePlaceholder:
            return m_view.background(KColorScheme::NegativeBackground).color();
    }
    qFatal("Unhandled color requested: %d\n", role);
    return QColor();
}

QColor KateDefaultColors::mark(Mark mark) const
{
    // note: the mark color is used as background color at very low opacity (around 0.1)
    // hence, make sure the color returned here has a high saturation
    switch (mark) {
        case Bookmark:
            return adaptToScheme(Qt::blue, BackgroundColor);
        case ActiveBreakpoint:
            return adaptToScheme(Qt::red, BackgroundColor);
        case ReachedBreakpoint:
            return adaptToScheme(Qt::yellow, BackgroundColor);
        case DisabledBreakpoint:
            return adaptToScheme(Qt::magenta, BackgroundColor);
        case Execution:
            return adaptToScheme(Qt::gray, BackgroundColor);
        case Warning:
            return m_view.foreground(KColorScheme::NeutralText).color();
        case Error:
            return m_view.foreground(KColorScheme::NegativeText).color();
    }
    qFatal("Unhandled color for mark requested: %d\n", mark);
    return QColor();
}

QColor KateDefaultColors::mark(int i) const
{
    Q_ASSERT(i >= FIRST_MARK && i <= LAST_MARK);
    return mark(static_cast<Mark>(i));
}

QColor KateDefaultColors::adaptToScheme(const QColor &color, ColorType type) const
{
    if (m_foregroundLuma > m_backgroundLuma) {
        // for dark color schemes, produce a fitting color by tinting with the foreground/background color
        return KColorUtils::tint(type == ForegroundColor ? m_foreground : m_background, color, 0.5);
    }
    return color;
}
