/*
 *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
 *  Copyright (C) 2008 Nuanti Ltd.
 *  Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
 *  Copyright (C) 2009-2010 ProFUSION embedded systems
 *  Copyright (C) 2009-2010 Samsung Electronics
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "EditorClientEfl.h"

#include "DumpRenderTreeSupportEfl.h"
#include "Editor.h"
#include "EflKeyboardUtilities.h"
#include "EventNames.h"
#include "FocusController.h"
#include "Frame.h"
#include "KeyboardEvent.h"
#include "NotImplemented.h"
#include "Page.h"
#include "PlatformKeyboardEvent.h"
#include "Settings.h"
#include "UndoStep.h"
#include "WindowsKeyboardCodes.h"
#include "ewk_frame_private.h"
#include "ewk_private.h"
#include "ewk_view_private.h"

using namespace WebCore;

namespace WebCore {

void EditorClientEfl::willSetInputMethodState()
{
    notImplemented();
}

void EditorClientEfl::setInputMethodState(bool active)
{
    ewk_view_input_method_state_set(m_view, active);
}

bool EditorClientEfl::shouldDeleteRange(Range* range)
{
    evas_object_smart_callback_call(m_view, "editorclient,range,delete", range);
    return true;
}

bool EditorClientEfl::shouldShowDeleteInterface(HTMLElement*)
{
    return false;
}

bool EditorClientEfl::isContinuousSpellCheckingEnabled()
{
    notImplemented();
    return false;
}

bool EditorClientEfl::isGrammarCheckingEnabled()
{
    notImplemented();
    return false;
}

int EditorClientEfl::spellCheckerDocumentTag()
{
    notImplemented();
    return 0;
}

bool EditorClientEfl::shouldBeginEditing(Range* range)
{
    evas_object_smart_callback_call(m_view, "editorclient,editing,begin", range);
    return true;
}

bool EditorClientEfl::shouldEndEditing(Range* range)
{
    evas_object_smart_callback_call(m_view, "editorclient,editing,end", range);
    return true;
}

bool EditorClientEfl::shouldInsertText(const String& text, Range* range, EditorInsertAction action)
{
    CString protectedText = text.utf8();
    Ewk_Should_Insert_Text_Event shouldInsertTextEvent = { protectedText.data(), range, action };
    evas_object_smart_callback_call(m_view, "editorclient,text,insert", &shouldInsertTextEvent);
    return true;
}

bool EditorClientEfl::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting)
{
    Ewk_Should_Change_Selected_Range_Event shouldChangeSelectedRangeEvent = { fromRange, toRange, affinity, stillSelecting };
    evas_object_smart_callback_call(m_view, "editorclient,selected,range,change", &shouldChangeSelectedRangeEvent);
    return true;
}

bool EditorClientEfl::shouldApplyStyle(StylePropertySet* style, Range* range)
{
    Ewk_Should_Apply_Style_Event shouldApplyStyleEvent = { style, range };
    evas_object_smart_callback_call(m_view, "editorclient,style,apply", &shouldApplyStyleEvent);
    return true;
}

bool EditorClientEfl::shouldMoveRangeAfterDelete(Range*, Range*)
{
    notImplemented();
    return true;
}

void EditorClientEfl::didBeginEditing()
{
    evas_object_smart_callback_call(m_view, "editorclient,editing,began", 0);
}

void EditorClientEfl::respondToChangedContents()
{
    Evas_Object* frame = ewk_view_frame_focused_get(m_view);

    if (!frame)
        frame = ewk_view_frame_main_get(m_view);

    if (!frame)
        return;

    ewk_frame_editor_client_contents_changed(frame);
}

void EditorClientEfl::respondToChangedSelection(Frame* coreFrame)
{
    if (!coreFrame)
        return;

    if (coreFrame->editor() && coreFrame->editor()->ignoreCompositionSelectionChange())
        return;

    Evas_Object* webFrame = EWKPrivate::kitFrame(coreFrame);
    ewk_frame_editor_client_selection_changed(webFrame);

    if (!coreFrame->editor()->hasComposition() || coreFrame->editor()->ignoreCompositionSelectionChange())
        return;

    unsigned start;
    unsigned end;

    if (!coreFrame->editor()->getCompositionSelection(start, end))
        coreFrame->editor()->cancelComposition();
}

void EditorClientEfl::didEndEditing()
{
    evas_object_smart_callback_call(m_view, "editorclient,editing,ended", 0);
}

void EditorClientEfl::didWriteSelectionToPasteboard()
{
    notImplemented();
}

void EditorClientEfl::didSetSelectionTypesForPasteboard()
{
    notImplemented();
}

void EditorClientEfl::registerUndoStep(WTF::PassRefPtr<UndoStep> step)
{
    if (!m_isInRedo)
        redoStack.clear();
    undoStack.prepend(step);
}

void EditorClientEfl::registerRedoStep(WTF::PassRefPtr<UndoStep> step)
{
    redoStack.prepend(step);
}

void EditorClientEfl::clearUndoRedoOperations()
{
    undoStack.clear();
    redoStack.clear();
}

bool EditorClientEfl::canCopyCut(Frame*, bool defaultValue) const
{
    return defaultValue;
}

bool EditorClientEfl::canPaste(Frame*, bool defaultValue) const
{
    return defaultValue;
}

bool EditorClientEfl::canUndo() const
{
    return !undoStack.isEmpty();
}

bool EditorClientEfl::canRedo() const
{
    return !redoStack.isEmpty();
}

void EditorClientEfl::undo()
{
    if (canUndo()) {
        RefPtr<WebCore::UndoStep> step = undoStack.takeFirst();
        step->unapply();
    }
}

void EditorClientEfl::redo()
{
    if (canRedo()) {
        RefPtr<WebCore::UndoStep> step = redoStack.takeFirst();

        ASSERT(!m_isInRedo);
        m_isInRedo = true;
        step->reapply();
        m_isInRedo = false;
    }
}

bool EditorClientEfl::shouldInsertNode(Node* node, Range* range, EditorInsertAction action)
{
    Ewk_Should_Insert_Node_Event insertNodeEvent = { node, range, action };
    evas_object_smart_callback_call(m_view, "editorclient,node,insert", &insertNodeEvent);
    return true;
}

void EditorClientEfl::pageDestroyed()
{
    delete this;
}

void EditorClientEfl::setSmartInsertDeleteEnabled(bool enabled)
{
    m_smartInsertDeleteEnabled = enabled;
    if (enabled)
        setSelectTrailingWhitespaceEnabled(false);
}

bool EditorClientEfl::smartInsertDeleteEnabled()
{
    return m_smartInsertDeleteEnabled;
}

void EditorClientEfl::setSelectTrailingWhitespaceEnabled(bool enabled)
{
    m_selectTrailingWhitespaceEnabled = enabled;
    if (enabled)
        setSmartInsertDeleteEnabled(false);
}

bool EditorClientEfl::isSelectTrailingWhitespaceEnabled()
{
    return m_selectTrailingWhitespaceEnabled;
}

void EditorClientEfl::toggleContinuousSpellChecking()
{
    notImplemented();
}

void EditorClientEfl::toggleGrammarChecking()
{
    notImplemented();
}

const char* EditorClientEfl::interpretKeyEvent(const KeyboardEvent* event)
{
    ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);

    if (event->type() == eventNames().keydownEvent)
        return getKeyDownCommandName(event);

    return getKeyPressCommandName(event);
}

bool EditorClientEfl::handleEditingKeyboardEvent(KeyboardEvent* event)
{
    Node* node = event->target()->toNode();
    ASSERT(node);
    Frame* frame = node->document()->frame();
    ASSERT(frame);

    const PlatformKeyboardEvent* keyEvent = event->keyEvent();
    if (!keyEvent)
        return false;

    if (!frame->settings())
        return false;

    bool caretBrowsing = frame->settings()->caretBrowsingEnabled();
    if (caretBrowsing) {
        switch (keyEvent->windowsVirtualKeyCode()) {
        case VK_LEFT:
            frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove,
                                       DirectionLeft,
                                       keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity,
                                       UserTriggered);
            return true;
        case VK_RIGHT:
            frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove,
                                       DirectionRight,
                                       keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity,
                                       UserTriggered);
            return true;
        case VK_UP:
            frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove,
                                       DirectionBackward,
                                       keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity,
                                       UserTriggered);
            return true;
        case VK_DOWN:
            frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove,
                                       DirectionForward,
                                       keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity,
                                       UserTriggered);
            return true;
        }
    }

    Editor::Command command = frame->editor()->command(interpretKeyEvent(event));

    if (keyEvent->type() == PlatformEvent::RawKeyDown) {
        // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
        // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
        // (e.g. Tab that inserts a Tab character, or Enter).
        return !command.isTextInsertion() && command.execute(event);
    }

    if (command.execute(event))
        return true;

    // Don't allow text insertion for nodes that cannot edit.
    if (!frame->editor()->canEdit())
        return false;

    // Don't insert null or control characters as they can result in unexpected behaviour
    if (event->charCode() < ' ')
        return false;

    // Don't insert anything if a modifier is pressed
    if (keyEvent->ctrlKey() || keyEvent->altKey())
        return false;

    return frame->editor()->insertText(event->keyEvent()->text(), event);
}

void EditorClientEfl::handleKeyboardEvent(KeyboardEvent* event)
{
    if (handleEditingKeyboardEvent(event))
        event->setDefaultHandled();
}

void EditorClientEfl::handleInputMethodKeydown(KeyboardEvent*)
{
}

EditorClientEfl::EditorClientEfl(Evas_Object* view)
    : m_isInRedo(false)
    , m_view(view)
    , m_selectTrailingWhitespaceEnabled(false)
    , m_smartInsertDeleteEnabled(false)
{
    notImplemented();
}

EditorClientEfl::~EditorClientEfl()
{
    notImplemented();
}

void EditorClientEfl::textFieldDidBeginEditing(Element*)
{
}

void EditorClientEfl::textFieldDidEndEditing(Element*)
{
    notImplemented();
}

void EditorClientEfl::textDidChangeInTextField(Element*)
{
    notImplemented();
}

bool EditorClientEfl::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
{
    return false;
}

void EditorClientEfl::textWillBeDeletedInTextField(Element*)
{
    notImplemented();
}

void EditorClientEfl::textDidChangeInTextArea(Element*)
{
    notImplemented();
}

bool EditorClientEfl::shouldEraseMarkersAfterChangeSelection(TextCheckingType) const
{
    return true;
}

void EditorClientEfl::ignoreWordInSpellDocument(const String&)
{
    notImplemented();
}

void EditorClientEfl::learnWord(const String&)
{
    notImplemented();
}

void EditorClientEfl::checkSpellingOfString(const UChar*, int, int*, int*)
{
    notImplemented();
}

String EditorClientEfl::getAutoCorrectSuggestionForMisspelledWord(const String&)
{
    notImplemented();
    return String();
}

void EditorClientEfl::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
{
    notImplemented();
}

void EditorClientEfl::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
{
    notImplemented();
}

void EditorClientEfl::updateSpellingUIWithMisspelledWord(const String&)
{
    notImplemented();
}

void EditorClientEfl::showSpellingUI(bool)
{
    notImplemented();
}

bool EditorClientEfl::spellingUIIsShowing()
{
    notImplemented();
    return false;
}

void EditorClientEfl::getGuessesForWord(const String& /*word*/, const String& /*context*/, Vector<String>& /*guesses*/)
{
    notImplemented();
}

}
