/*
 * Copyright (C) 2011 Samsung Electronics
 * Copyright (C) 2012 Intel Corporation. All rights reserved.
 *
 * 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 "config.h"
#include "InputMethodContextEfl.h"

#include "EwkView.h"
#include "WebPageProxy.h"
#include <Ecore_Evas.h>
#include <Ecore_IMF_Evas.h>
#include <WebCore/Editor.h>

using namespace WebCore;

namespace WebKit {

InputMethodContextEfl::InputMethodContextEfl(EwkView* view, EflUniquePtr<Ecore_IMF_Context> context)
    : m_view(view)
    , m_context(WTFMove(context))
    , m_focused(false)
{
    ASSERT(m_context);
    ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
    ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
}

InputMethodContextEfl::~InputMethodContextEfl()
{
}

void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
{
    InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
    if (!eventInfo || !inputMethodContext->m_focused)
        return;

    inputMethodContext->m_view->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
}

void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
{
    InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);

    if (!inputMethodContext->m_view->page()->focusedFrame() || !inputMethodContext->m_focused)
        return;

    char* buffer = 0;
    ecore_imf_context_preedit_string_get(context, &buffer, 0);
    if (!buffer)
        return;

    String preeditString = String::fromUTF8(buffer);
    free(buffer);
    Vector<CompositionUnderline> underlines;
    underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
    inputMethodContext->m_view->page()->setComposition(preeditString, underlines, 0);
}

EflUniquePtr<Ecore_IMF_Context> InputMethodContextEfl::createIMFContext(Evas* canvas)
{
    const char* defaultContextID = ecore_imf_context_default_id_get();
    if (!defaultContextID)
        return nullptr;

    EflUniquePtr<Ecore_IMF_Context> imfContext(ecore_imf_context_add(defaultContextID));
    if (!imfContext)
        return nullptr;

    Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(canvas);
    ecore_imf_context_client_window_set(imfContext.get(), reinterpret_cast<void*>(ecore_evas_window_get(ecoreEvas)));
    ecore_imf_context_client_canvas_set(imfContext.get(), canvas);

    return imfContext;
}

void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
{
    ecore_imf_context_reset(m_context.get());
}

void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
{
    Ecore_IMF_Event inputMethodEvent;
    ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(downEvent), &inputMethodEvent.key_down);

    *isFiltered = ecore_imf_context_filter_event(m_context.get(), ECORE_IMF_EVENT_KEY_DOWN, &inputMethodEvent);
}

void InputMethodContextEfl::updateTextInputState()
{
    if (!m_context)
        return;

    const EditorState& editor = m_view->page()->editorState();

    if (editor.isContentEditable) {
        if (m_focused)
            return;

        ecore_imf_context_reset(m_context.get());
        ecore_imf_context_focus_in(m_context.get());
        m_focused = true;
    } else {
        if (!m_focused)
            return;

        if (editor.hasComposition)
            m_view->page()->cancelComposition();

        m_focused = false;
        ecore_imf_context_reset(m_context.get());
        ecore_imf_context_focus_out(m_context.get());
    }
}

}
