// Copyright 2021 Google LLC.
#include "experimental/sktext/editor/Editor.h"
#include "experimental/sktext/src/Paint.h"

using namespace skia::text;

namespace skia {
namespace editor {

std::unique_ptr<Editor> Editor::Make(std::u16string text, SkSize size) {
    return std::make_unique<Editor>(text, size);
}

Editor::Editor(std::u16string text, SkSize size)
        : fDefaultPositionType(PositionType::kGraphemeCluster)
        , fInsertMode(true) {

    fParent = nullptr;
    fCursor = Cursor::Make();
    fMouse = std::make_unique<Mouse>();
    {
        SkPaint foreground; foreground.setColor(DEFAULT_TEXT_FOREGROUND);
        SkPaint background; background.setColor(DEFAULT_TEXT_BACKGROUND);
        static FontBlock textBlock(text.size(), sk_make_sp<TrivialFontChain>("Roboto", 40, SkFontStyle::Normal()));
        static DecoratedBlock textDecor(text.size(), foreground, background);
        auto textSize = SkSize::Make(size.width(), size.height() - DEFAULT_STATUS_HEIGHT);
        fEditableText = std::make_unique<EditableText>(
                text, SkPoint::Make(0, 0), textSize,
                SkSpan<FontBlock>(&textBlock, 1), SkSpan<DecoratedBlock>(&textDecor, 1),
                DEFAULT_TEXT_DIRECTION, DEFAULT_TEXT_ALIGN);
    }
    {
        SkPaint foreground; foreground.setColor(DEFAULT_STATUS_FOREGROUND);
        SkPaint background; background.setColor(DEFAULT_STATUS_BACKGROUND);
        std::u16string status = u"This is the status line";
        static FontBlock statusBlock(status.size(), sk_make_sp<TrivialFontChain>("Roboto", 20, SkFontStyle::Normal()));
        static DecoratedBlock statusDecor(status.size(), foreground, background);
        auto statusPoint = SkPoint::Make(0, size.height() - DEFAULT_STATUS_HEIGHT);
        fStatus = std::make_unique<DynamicText>(
                status, statusPoint, SkSize::Make(size.width(), SK_ScalarInfinity),
                SkSpan<FontBlock>(&statusBlock, 1), SkSpan<DecoratedBlock>(&statusDecor, 1),
                        DEFAULT_TEXT_DIRECTION, TextAlign::kCenter);
    }
    // Place the cursor at the end of the output text
    // (which is the end of the text for LTR and the beginning of the text for RTL
    // or possibly something in the middle for a combination of LTR & RTL)
    // In order to get that position we look for a position outside of the text
    // and that will give us the last glyph on the line
    auto endOfText = fEditableText->lastElement(fDefaultPositionType);
    //fEditableText->recalculateBoundaries(endOfText);
    fCursor->place(endOfText.fBoundaries);
}

void Editor::update() {

    if (fEditableText->isValid()) {
        return;
    }

    // Update the (shift it to point at the grapheme edge)
    auto position = fEditableText->adjustedPosition(fDefaultPositionType, fCursor->getCenterPosition());
    //fEditableText->recalculateBoundaries(position);
    fCursor->place(position.fBoundaries);

    // TODO: Update the mouse
    fMouse->clearTouchInfo();
}

// Moving the cursor by the output grapheme clusters (shifting to another line if necessary)
// We don't want to move by the input text indexes because then we will have to take in account LTR/RTL
bool Editor::moveCursor(skui::Key key) {
    auto cursorPosition = fCursor->getCenterPosition();
    auto position = fEditableText->adjustedPosition(PositionType::kGraphemeCluster, cursorPosition);

    if (key == skui::Key::kLeft) {
        position = fEditableText->previousElement(position);
    } else if (key == skui::Key::kRight) {
        position = fEditableText->nextElement(position);
    } else if (key == skui::Key::kHome) {
        position = fEditableText->firstElement(PositionType::kGraphemeCluster);
    } else if (key == skui::Key::kEnd) {
        position = fEditableText->lastElement(PositionType::kGraphemeCluster);
    } else if (key == skui::Key::kUp) {
        // Move one line up (if possible)
        if (position.fLineIndex == 0) {
            return false;
        }
        auto prevLine = fEditableText->getLine(position.fLineIndex - 1);
        cursorPosition.offset(0, - prevLine.fBounds.height());
        position = fEditableText->adjustedPosition(PositionType::kGraphemeCluster, cursorPosition);
    } else if (key == skui::Key::kDown) {
        // Move one line down (if possible)
        if (position.fLineIndex == fEditableText->lineCount() - 1) {
            return false;
        }
        auto nextLine = fEditableText->getLine(position.fLineIndex + 1);
        cursorPosition.offset(0, nextLine.fBounds.height());
        position = fEditableText->adjustedPosition(PositionType::kGraphemeCluster, cursorPosition);
     }

    // Place the cursor at the new position
    //fEditableText->recalculateBoundaries(position);
    fCursor->place(position.fBoundaries);
    this->invalidate();

    return true;
}

void Editor::onPaint(SkSurface* surface) {
    SkCanvas* canvas = surface->getCanvas();
    SkAutoCanvasRestore acr(canvas, true);
    canvas->clipRect({0, 0, (float)fWidth, (float)fHeight});
    canvas->drawColor(SK_ColorWHITE);
    this->paint(canvas);
}

void Editor::onResize(int width, int height) {
    if (SkISize{fWidth, fHeight} != SkISize{width, height}) {
        fHeight = height;
        if (width != fWidth) {
            fWidth = width;
        }
        this->invalidate();
    }
}

bool Editor::onChar(SkUnichar c, skui::ModifierKey modi) {
    using sknonstd::Any;

    modi &= ~skui::ModifierKey::kFirstPress;
    if (!Any(modi & (skui::ModifierKey::kControl |
                     skui::ModifierKey::kOption |
                     skui::ModifierKey::kCommand))) {
        if (((unsigned)c < 0x7F && (unsigned)c >= 0x20) || c == 0x000A) {
            insertCodepoint(c);
            return true;
        }
    }
    static constexpr skui::ModifierKey kCommandOrControl =
            skui::ModifierKey::kCommand | skui::ModifierKey::kControl;
    if (Any(modi & kCommandOrControl) && !Any(modi & ~kCommandOrControl)) {
        return false;
    }
    return false;
}

bool Editor::deleteElement(skui::Key key) {

    if (fEditableText->isEmpty()) {
        return false;
    }

    auto cursorPosition = fCursor->getCenterPosition();
    auto position = fEditableText->adjustedPosition(fDefaultPositionType, cursorPosition);
    TextRange textRange = position.fTextRange;

    // IMPORTANT: We assume that a single element (grapheme cluster) does not cross the run boundaries;
    // It's not exactly true but we are going to enforce in by breaking the grapheme by the run boundaries
    if (key == skui::Key::kBack) {
        // TODO: Make sure previous element moves smoothly over the line break
        position = fEditableText->previousElement(position);
        textRange = position.fTextRange;
        fCursor->place(position.fBoundaries);
    } else {
        // The cursor stays the the same place
    }

    fEditableText->removeElement(textRange);

    // Find the grapheme the cursor points to
    position = fEditableText->adjustedPosition(fDefaultPositionType, SkPoint::Make(position.fBoundaries.fLeft, position.fBoundaries.fTop));
    fCursor->place(position.fBoundaries);
    this->invalidate();

    return true;
}

bool Editor::insertCodepoint(SkUnichar unichar) {
    auto cursorPosition = fCursor->getCenterPosition();
    auto position = fEditableText->adjustedPosition(fDefaultPositionType, cursorPosition);

    if (fInsertMode) {
        fEditableText->insertElement(unichar, position.fTextRange.fStart);
    } else {
        fEditableText->replaceElement(unichar, position.fTextRange);
    }

    this->update();

    // Find the element the cursor points to
    position = fEditableText->adjustedPosition(fDefaultPositionType, cursorPosition);

    // Move the cursor to the next element
    position = fEditableText->nextElement(position);
    //fEditableText->recalculateBoundaries(position);
    fCursor->place(position.fBoundaries);

    this->invalidate();

    return true;
}

bool Editor::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) {

    if (state != skui::InputState::kDown) {
        return false;
    }
    using sknonstd::Any;
    skui::ModifierKey ctrlAltCmd = modifiers & (skui::ModifierKey::kControl |
                                                skui::ModifierKey::kOption  |
                                                skui::ModifierKey::kCommand);
    //bool shift = Any(modifiers & (skui::ModifierKey::kShift));
    if (!Any(ctrlAltCmd)) {
        // no modifiers
        switch (key) {
            case skui::Key::kLeft:
            case skui::Key::kRight:
            case skui::Key::kUp:
            case skui::Key::kDown:
            case skui::Key::kHome:
            case skui::Key::kEnd:
                this->moveCursor(key);
                break;
            case skui::Key::kDelete:
            case skui::Key::kBack:
                this->deleteElement(key);
                return true;
            case skui::Key::kOK:
                return this->onChar(0x000A, modifiers);
            default:
                break;
        }
    }
    return false;
}

bool Editor::onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) {

    if (!fEditableText->contains(x, y)) {
        // We only support mouse on an editable area
    }
    if (skui::InputState::kDown == state) {
        auto position = fEditableText->adjustedPosition(fDefaultPositionType, SkPoint::Make(x, y));
        if (fMouse->isDoubleClick(SkPoint::Make(x, y))) {
            // Select the element
            fEditableText->select(position.fTextRange, position.fBoundaries);
            position.fBoundaries.fLeft = position.fBoundaries.fRight - DEFAULT_CURSOR_WIDTH;
            // Clear mouse
            fMouse->up();
        } else {
            // Clear selection
            fMouse->down();
            fEditableText->clearSelection();
        }

        fCursor->place(position.fBoundaries);
        this->invalidate();
        return true;
    }
    fMouse->up();
    return false;
}

void Editor::paint(SkCanvas* canvas) {

    fEditableText->paint(canvas);
    fCursor->paint(canvas);

    SkPaint background; background.setColor(DEFAULT_STATUS_BACKGROUND);
    canvas->drawRect(SkRect::MakeXYWH(0, fHeight - DEFAULT_STATUS_HEIGHT, fWidth, DEFAULT_STATUS_HEIGHT), background);
    fStatus->paint(canvas);
}

std::unique_ptr<Editor> Editor::MakeDemo(SkScalar width, SkScalar height) {

    std::u16string text0 = u"In a hole in the ground there lived a hobbit. Not a nasty, dirty, "
                            "wet hole full of worms and oozy smells.\nThis was a hobbit-hole and "
                            "that means good food, a warm hearth, and all the comforts of home.";

    return Editor::Make(text0, SkSize::Make(width, height));
}
} // namespace editor
} // namespace skia
