/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "tools/sk_app/CommandSet.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "src/core/SkTSort.h"

namespace sk_app {

CommandSet::CommandSet()
    : fHelpMode(kNone_HelpMode) {
    this->addCommand('h', "Overlays", "Show help screen", [this]() {
        switch (this->fHelpMode) {
            case kNone_HelpMode:
                this->fHelpMode = kGrouped_HelpMode;
                break;
            case kGrouped_HelpMode:
                this->fHelpMode = kAlphabetical_HelpMode;
                break;
            case kAlphabetical_HelpMode:
                this->fHelpMode = kNone_HelpMode;
                break;
        }
        fWindow->inval();
    });
}

void CommandSet::attach(Window* window) {
    fWindow = window;
}

bool CommandSet::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) {
    if (skui::InputState::kDown == state) {
        for (Command& cmd : fCommands) {
            if (Command::kKey_CommandType == cmd.fType && key == cmd.fKey) {
                cmd.fFunction();
                return true;
            }
        }
    }

    return false;
}

bool CommandSet::onChar(SkUnichar c, skui::ModifierKey modifiers) {
    for (Command& cmd : fCommands) {
        if (Command::kChar_CommandType == cmd.fType && c == cmd.fChar) {
            cmd.fFunction();
            return true;
        }
    }

    return false;
}

bool CommandSet::onSoftkey(const SkString& softkey) {
    for (const Command& cmd : fCommands) {
        if (cmd.getSoftkeyString().equals(softkey)) {
            cmd.fFunction();
            return true;
        }
    }
    return false;
}

void CommandSet::addCommand(SkUnichar c, const char* group, const char* description,
                            std::function<void(void)> function) {
    fCommands.push_back(Command(c, group, description, function));
}

void CommandSet::addCommand(skui::Key k, const char* keyName, const char* group,
                            const char* description, std::function<void(void)> function) {
    fCommands.push_back(Command(k, keyName, group, description, function));
}

#if defined(SK_BUILD_FOR_WIN)
    #define SK_strcasecmp   _stricmp
#else
    #define SK_strcasecmp   strcasecmp
#endif

bool CommandSet::compareCommandKey(const Command& first, const Command& second) {
    return SK_strcasecmp(first.fKeyName.c_str(), second.fKeyName.c_str()) < 0;
}

bool CommandSet::compareCommandGroup(const Command& first, const Command& second) {
    return SK_strcasecmp(first.fGroup.c_str(), second.fGroup.c_str()) < 0;
}

void CommandSet::drawHelp(SkCanvas* canvas) {
    if (kNone_HelpMode == fHelpMode) {
        return;
    }

    // Sort commands for current mode:
    SkTQSort(fCommands.begin(), fCommands.end() - 1,
             kAlphabetical_HelpMode == fHelpMode ? compareCommandKey : compareCommandGroup);

    SkFont font;
    font.setSize(16);

    SkFont groupFont;
    groupFont.setSize(18);

    SkPaint bgPaint;
    bgPaint.setColor(0xC0000000);
    canvas->drawPaint(bgPaint);

    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(0xFFFFFFFF);

    SkPaint groupPaint;
    groupPaint.setAntiAlias(true);
    groupPaint.setColor(0xFFFFFFFF);

    SkScalar x = SkIntToScalar(10);
    SkScalar y = SkIntToScalar(10);

    // Measure all key strings:
    SkScalar keyWidth = 0;
    for (Command& cmd : fCommands) {
        keyWidth = SkMaxScalar(keyWidth,
                               font.measureText(cmd.fKeyName.c_str(), cmd.fKeyName.size(),
                                                SkTextEncoding::kUTF8));
    }
    keyWidth += font.measureText(" ", 1, SkTextEncoding::kUTF8);

    // If we're grouping by category, we'll be adding text height on every new group (including the
    // first), so no need to do that here. Otherwise, skip down so the first line is where we want.
    if (kGrouped_HelpMode != fHelpMode) {
        y += font.getSize();
    }

    // Print everything:
    SkString lastGroup;
    for (Command& cmd : fCommands) {
        if (kGrouped_HelpMode == fHelpMode && lastGroup != cmd.fGroup) {
            // Group change. Advance and print header:
            y += font.getSize();
            canvas->drawSimpleText(cmd.fGroup.c_str(), cmd.fGroup.size(), SkTextEncoding::kUTF8,
                                   x, y, groupFont, groupPaint);
            y += groupFont.getSize() + 2;
            lastGroup = cmd.fGroup;
        }

        canvas->drawSimpleText(cmd.fKeyName.c_str(), cmd.fKeyName.size(), SkTextEncoding::kUTF8,
                               x, y, font, paint);
        SkString text = SkStringPrintf(": %s", cmd.fDescription.c_str());
        canvas->drawString(text, x + keyWidth, y, font, paint);
        y += font.getSize() + 2;
    }
}

std::vector<SkString> CommandSet::getCommandsAsSoftkeys() const {
    std::vector<SkString> result;
    for(const Command& command : fCommands) {
        result.push_back(command.getSoftkeyString());
    }
    return result;
}

}   // namespace sk_app
