// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "win32/ime/ime_core.h"

#include <ime.h>
#include <windows.h>

#include <memory>

#include "base/logging.h"
#include "base/util.h"
#include "client/client_interface.h"
#include "config/config_handler.h"
#include "session/commands.pb.h"
#include "session/output_util.h"
#include "win32/base/conversion_mode_util.h"
#include "win32/base/deleter.h"
#include "win32/base/input_state.h"
#include "win32/base/keyboard.h"
#include "win32/base/imm_reconvert_string.h"
#include "win32/ime/ime_candidate_info.h"
#include "win32/ime/ime_composition_string.h"
#include "win32/ime/ime_private_context.h"
#include "win32/ime/ime_scoped_context.h"
#include "win32/ime/ime_ui_context.h"
#include "win32/ime/ime_ui_visibility_tracker.h"

namespace mozc {
namespace win32 {

using commands::KeyEvent;
using commands::Output;
using commands::SessionCommand;
using std::unique_ptr;

namespace {

const size_t kReconvertStringSizeLimit = 1024*64;
// An embedded object in the RichEdit will be replaced with this character.
// See b/3406434 for details.
const wchar_t kObjectReplacementCharacter = L'\uFFFC';

bool GetNextState(HIMC himc, const commands::Output &output,
                  mozc::win32::InputState *next_state) {
  DCHECK(next_state);

  UIContext context(himc);
  bool next_open_status = false;
  DWORD next_logical_mode = 0;
  DWORD next_visible_mode = 0;
  if (!output.has_status()) {
    // |output| does not have |status|.  Preserve the current status.
    next_open_status = context.GetOpenStatus();
    if (!context.GetConversionMode(&next_logical_mode)) {
      return false;
    }
    next_visible_mode = next_logical_mode;
  } else if (!mozc::win32::ConversionModeUtil::ConvertStatusFromMozcToNative(
      output.status(), context.IsKanaInputPreferred(),
      &next_open_status, &next_logical_mode, &next_visible_mode)) {
    return false;
  }

  next_state->open = next_open_status;
  next_state->logical_conversion_mode = next_logical_mode;
  next_state->visible_conversion_mode = next_visible_mode;
  return true;
}

bool UpdateInputContext(
    HIMC himc, const commands::Output &output, bool generate_message) {
  InputState next_state;
  if (!GetNextState(himc, output, &next_state)) {
    return false;
  }
  if (!generate_message) {
    if (!ImeCore::UpdateContext(himc, next_state, output, nullptr)) {
      return false;
    }
    return true;
  }
  MessageQueue message_queue(himc);
  if (!ImeCore::UpdateContext(himc, next_state, output, &message_queue)) {
    return FALSE;
  }
  return message_queue.Send();
}

HIMCC EnsureHIMCCSize(HIMCC himcc, DWORD size) {
  if (himcc == nullptr) {
    return ::ImmCreateIMCC(size);
  }
  const DWORD current_size = ::ImmGetIMCCSize(himcc);
  if (current_size == size) {
    return himcc;
  }
  return ::ImmReSizeIMCC(himcc, size);
}

bool UpdateCompositionString(HIMC himc,
                             const commands::Output &output,
                             vector<UIMessage> *messages) {
  ScopedHIMC<InputContext> context(himc);

  // When the string is inserted from Tablet Input Panel, MSCTF shrinks the
  // CompositionString buffer that we allocated in ImeSelect(). Thus we need
  // to resize the buffer when necessary. b/6841008
  // TODO(yukawa): Move this logic into more appropriate place.
  const HIMCC composition_string_handle = EnsureHIMCCSize(
      context->hCompStr, sizeof(CompositionString));
  if (composition_string_handle == nullptr) {
    return false;
  }
  ScopedHIMCC<CompositionString> compstr(composition_string_handle);
  if (!compstr->Update(output, messages)) {
    return false;
  }
  return true;
}

bool UpdateCompositionStringAndPushMessages(
    HIMC himc,
    const commands::Output &output,
    MessageQueue *message_queue) {
  ScopedHIMC<InputContext> context(himc);
  ScopedHIMCC<PrivateContext> private_context(context->hPrivate);
  vector<UIMessage> messages;

  if (!UpdateCompositionString(himc, output, &messages)) {
    return false;
  }

  const bool generate_message = (message_queue != nullptr);
  if (!generate_message) {
    return true;
  }

  for (vector<UIMessage>::const_iterator it = messages.begin();
       it != messages.end(); ++it) {
    if (UIVisibilityTracker::IsVisibilityTestMessageForComposiwionWindow(
           it->message(), it->wparam(), it->lparam())) {
      private_context->ui_visibility_tracker->
        BeginVisibilityTestForCompositionWindow();
    }
    message_queue->AddMessage(it->message(), it->wparam(), it->lparam());
  }
  return true;
}

bool GetReconvertString(const RECONVERTSTRING *reconvert_string,
                        string *total_composition_in_utf8) {
  DCHECK(total_composition_in_utf8);
  total_composition_in_utf8->clear();

  if (reconvert_string->dwCompStrLen == 0) {
    // There is no text selection. Reconversion cannot be started.
    return false;
  }

  wstring preceding_composition;
  wstring target_text;
  wstring following_composition;
  if (!ReconvertString::Decompose(
          reconvert_string, nullptr, &preceding_composition,
          &target_text, &following_composition, nullptr)) {
    DLOG(INFO) << "ReconvertString::Decompose failed.";
    return false;
  }

  const wstring total_composition =
      preceding_composition + target_text + following_composition;

  // Like other Japanese IMEs (MS-IME, ATOK), Mozc does not support
  // reconversion when the composition string contains any embedded object
  // because it is too complicated to restore the original state when the
  // reconversion is canceled. See b/3406434 for details.
  if (total_composition.find(kObjectReplacementCharacter) != wstring::npos) {
    return false;
  }

  if ((Util::WideToUTF8(total_composition, total_composition_in_utf8) == 0) ||
      total_composition_in_utf8->empty()) {
    DLOG(INFO) << "Composition string is empty.";
    return false;
  }

  return true;
}

bool QueryDocumentFeed(HIMC himc,
                       wstring *preceding_text,
                       wstring *following_text) {
  LRESULT result = ::ImmRequestMessageW(himc, IMR_DOCUMENTFEED, 0);
  if (result == 0) {
    // IMR_DOCUMENTFEED is not supported.
    return false;
  }
  const size_t buffer_size = static_cast<size_t>(result);
  if (buffer_size > kReconvertStringSizeLimit) {
    LOG(ERROR) << "Too large RECONVERTSTRING.";
    return false;
  }

  unique_ptr<BYTE[]> buffer(new BYTE[buffer_size]);

  RECONVERTSTRING *reconvert_string =
      reinterpret_cast<RECONVERTSTRING *>(buffer.get());
  reconvert_string->dwSize = buffer_size;
  reconvert_string->dwVersion = 0;

  result = ::ImmRequestMessageW(himc, IMR_DOCUMENTFEED,
                                reinterpret_cast<LPARAM>(reconvert_string));
  if (result == 0) {
    DLOG(ERROR) << "RECONVERTSTRING is nullptr.";
    return false;
  }

  return ReconvertString::Decompose(
      reconvert_string, preceding_text, nullptr, nullptr, nullptr,
      following_text);
}

}  // namespace

void ImeCore::UpdateContextWithSurroundingText(HIMC himc,
                                               commands::Context *context) {
  if (context == nullptr) {
    return;
  }
  context->clear_preceding_text();
  context->clear_following_text();
  wstring preceding_text;
  wstring following_text;
  if (!QueryDocumentFeed(himc, &preceding_text, &following_text)) {
    return;
  }
  Util::WideToUTF8(preceding_text, context->mutable_preceding_text());
  Util::WideToUTF8(following_text, context->mutable_following_text());
}

KeyEventHandlerResult ImeCore::ImeProcessKey(
    mozc::client::ClientInterface *client,
    const VirtualKey &virtual_key,
    const LParamKeyInfo &lparam,
    const KeyboardStatus &keyboard_status,
    const InputBehavior &behavior,
    const InputState &initial_state,
    const mozc::commands::Context &context,
    InputState *next_state,
    commands::Output *output) {
  unique_ptr<Win32KeyboardInterface>
      keyboard(Win32KeyboardInterface::CreateDefault());
  return KeyEventHandler::ImeProcessKey(
      virtual_key, lparam.GetScanCode(), lparam.IsKeyDownInImeProcessKey(),
      keyboard_status, behavior, initial_state, context, client, keyboard.get(),
      next_state, output);
}

KeyEventHandlerResult ImeCore::ImeToAsciiEx(
    mozc::client::ClientInterface *client,
    const VirtualKey &virtual_key,
    BYTE scan_code,
    bool is_key_down,
    const KeyboardStatus &keyboard_status,
    const InputBehavior &behavior,
    const InputState &initial_state,
    const commands::Context &context,
    InputState *next_state,
    commands::Output *output) {
  unique_ptr<Win32KeyboardInterface>
      keyboard(Win32KeyboardInterface::CreateDefault());
  return KeyEventHandler::ImeToAsciiEx(
      virtual_key, scan_code, is_key_down, keyboard_status, behavior,
      initial_state, context, client, keyboard.get(), next_state, output);
}

bool ImeCore::OpenIME(mozc::client::ClientInterface *client, DWORD next_mode) {
  commands::CompositionMode mode = commands::DIRECT;
  if (!ConversionModeUtil::GetMozcModeFromNativeMode(next_mode, &mode)) {
    return false;
  }

  SessionCommand command;
  command.set_type(commands::SessionCommand::TURN_ON_IME);
  command.set_composition_mode(mode);
  commands::Output output;
  if (!client->SendCommand(command, &output)) {
    return false;
  }
  if (!output.consumed()) {
    return false;
  }
  return true;
}

bool ImeCore::CloseIME(mozc::client::ClientInterface *client,
                       DWORD next_mode, commands::Output *output) {
  commands::CompositionMode mode = commands::DIRECT;
  if (!ConversionModeUtil::GetMozcModeFromNativeMode(next_mode, &mode)) {
    return false;
  }

  SessionCommand command;
  command.set_type(commands::SessionCommand::TURN_OFF_IME);
  command.set_composition_mode(mode);

  if (!client->SendCommand(command, output)) {
    return false;
  }
  return true;
}

bool ImeCore::SubmitComposition(HIMC himc, bool generate_message) {
  UIContext context(himc);
  mozc::commands::Output output;
  mozc::commands::SessionCommand command;
  command.set_type(mozc::commands::SessionCommand::SUBMIT);
  if (!context.client()->SendCommand(command, &output)) {
    return false;
  }
  return UpdateInputContext(himc, output, generate_message);
}

bool ImeCore::CancelComposition(HIMC himc, bool generate_message) {
  UIContext context(himc);
  mozc::commands::Output output;
  mozc::commands::SessionCommand command;
  command.set_type(mozc::commands::SessionCommand::REVERT);
  if (!context.client()->SendCommand(command, &output)) {
    return false;
  }
  return UpdateInputContext(himc, output, generate_message);
}

bool ImeCore::SwitchInputMode(
    HIMC himc, DWORD native_mode, bool generate_message) {
  UIContext context(himc);

  const bool open = context.GetOpenStatus();
  if (!open) {
    return true;
  }
  mozc::commands::Output output;
  mozc::commands::SessionCommand command;
  command.set_type(mozc::commands::SessionCommand::SWITCH_INPUT_MODE);

  commands::CompositionMode mozc_mode = commands::HIRAGANA;
  if (!ConversionModeUtil::ToMozcMode(native_mode, &mozc_mode)) {
    return false;
  }

  command.set_composition_mode(mozc_mode);
  if (!context.client()->SendCommand(command, &output)) {
    return false;
  }
  return UpdateInputContext(himc, output, generate_message);
}

bool ImeCore::SendCallbackCommand(HIMC himc, bool generate_message) {
  UIContext context(himc);
  commands::Output last_output;
  context.GetLastOutput(&last_output);

  if (!last_output.has_callback()) {
    return false;
  }

  mozc::commands::Output output;
  if (!context.client()->SendCommand(last_output.callback().session_command(),
                                     &output)) {
    return false;
  }
  return UpdateInputContext(himc, output, generate_message);
}

DWORD ImeCore::GetSupportableConversionMode(DWORD raw_conversion_mode) {
  // If the initial |fdwConversion| is not a supported combination of flags,
  // we have to update it and then send the IMN_SETCONVERSIONMODE message.
  // See b/2914115 for details.
  const DWORD kHiragana = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE;
  const DWORD kFullKatakana = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE |
                              IME_CMODE_KATAKANA;
  const DWORD kHalfKatakana = IME_CMODE_NATIVE | IME_CMODE_KATAKANA;
  const DWORD kFullAlpha = IME_CMODE_ALPHANUMERIC | IME_CMODE_FULLSHAPE;
  const DWORD kHalfAlpha = IME_CMODE_ALPHANUMERIC;

  // Separate Roman flag
  DWORD roman_flag = (raw_conversion_mode & IME_CMODE_ROMAN);
  const DWORD original_mode = (raw_conversion_mode & ~IME_CMODE_ROMAN);

  DWORD next_mode = 0;
  switch (original_mode) {
    case kHiragana:
    case kFullKatakana:
    case kHalfKatakana:
    case kFullAlpha:
    case kHalfAlpha:
      // OK, this is one of Well-known modes.
      next_mode = original_mode;
      break;
    default:
      // Unknown combination.
      // TODO(yukawa): use most similar mode instead of always choosing
      //   Roman-Hiragana
      next_mode = kHiragana;
      roman_flag = IME_CMODE_ROMAN;
      break;
  }

  // Restore Roman Flag
  next_mode |= roman_flag;

  return next_mode;
}

DWORD ImeCore::GetSupportableSentenceMode(DWORD raw_sentence_mode) {
  // If the initial |fdwSentence| is not a supported combination of flags,
  // we have to update it and then send the IMN_SETSENTENCEMODE message as we
  // did in b/2914115 for conversion mode.

  // Always returns IME_SMODE_PHRASEPREDICT.
  // See b/2913510, b/2954777, and b/2955175 for details.
  return IME_SMODE_PHRASEPREDICT;
}

bool ImeCore::IsInputContextInitialized(HIMC himc) {
  if (himc == nullptr) {
    return false;
  }
  ScopedHIMC<InputContext> context(himc);
  // For some reason, we fail to lock input context.  See b/3088049 for
  // details.
  if (context.get() == nullptr) {
    return false;
  }
  if (!PrivateContextUtil::IsValidPrivateContext(context->hPrivate)) {
    return false;
  }
  ScopedHIMCC<PrivateContext> private_context(context->hPrivate);
  if (private_context->ime_behavior->disabled) {
    return false;
  }
  return true;
}

void ImeCore::SortIMEMessages(
    const vector<UIMessage> &composition_messages,
    const vector<UIMessage> &candidate_messages,
    bool previous_open_status,
    DWORD previous_conversion_mode,
    bool next_open_status,
    DWORD next_conversion_mode,
    vector<UIMessage> *sorted_messages) {
  DCHECK(sorted_messages);
  sorted_messages->clear();

  const bool open_status_changed =
      (previous_open_status != next_open_status);
  const bool conversion_mode_changed =
      (previous_conversion_mode != next_conversion_mode);

  // Notify IMN_SETOPENSTATUS for IME-ON.
  if (open_status_changed && next_open_status) {
    sorted_messages->push_back(UIMessage(WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0));
  }

  // Notify IMN_SETCONVERSIONMODE.
  if (conversion_mode_changed) {
    sorted_messages->push_back(UIMessage(
        WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0));
  }

  // Notify IMN_CLOSECANDIDATE.
  vector<UIMessage> other_candidate_messages;
  for (vector<UIMessage>::const_iterator it = candidate_messages.begin();
       it != candidate_messages.end(); ++it) {
    const bool is_close_candidate = ((it->message() == WM_IME_NOTIFY) &&
                                     (it->wparam() == IMN_CLOSECANDIDATE));
    if (!is_close_candidate) {
      other_candidate_messages.push_back(*it);
      continue;
    }
    sorted_messages->push_back(*it);
  }

  // Notify all composition UI messages except for WM_IME_ENDCOMPOSITION.
  // Typically WM_IME_STARTCOMPOSITION / WM_IME_COMPOSITION will be handled.
  vector<UIMessage> end_composition_messages;
  for (vector<UIMessage>::const_iterator it = composition_messages.begin();
       it != composition_messages.end(); ++it) {
    if (it->message() == WM_IME_ENDCOMPOSITION) {
      end_composition_messages.push_back(*it);
      continue;
    }
    sorted_messages->push_back(*it);
  }

  // Notify all other candidate UI messages.
  // Typically IMN_OPENCANDIDATE and IMN_CHANGECANDIDATE will be handled.
  for (vector<UIMessage>::const_iterator it = other_candidate_messages.begin();
       it != other_candidate_messages.end(); ++it) {
    DCHECK(!((it->message() == WM_IME_NOTIFY) &&
             (it->wparam() == IMN_CLOSECANDIDATE)));
    sorted_messages->push_back(*it);
  }

  // Notify WM_IME_ENDCOMPOSITION
  for (vector<UIMessage>::const_iterator it = end_composition_messages.begin();
       it != end_composition_messages.end(); ++it) {
    DCHECK_EQ(WM_IME_ENDCOMPOSITION, it->message());
    sorted_messages->push_back(*it);
  }

  // Notify IMN_SETOPENSTATUS for IME-OFF.
  if (open_status_changed && !next_open_status) {
    sorted_messages->push_back(UIMessage(WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0));
  }

  sorted_messages->push_back(
      UIMessage(WM_IME_NOTIFY, IMN_PRIVATE, kNotifyUpdateUI));
}

bool ImeCore::UpdateContext(HIMC himc,
                            const InputState &next_state,
                            const commands::Output &new_output,
                            MessageQueue *message_queue) {
  if (!IsInputContextInitialized(himc)) {
    return false;
  }

  if (!new_output.has_callback() ||
      !new_output.callback().has_session_command()) {
    // Callback is not requested.
    return UpdateContextMain(himc, next_state, new_output, message_queue);
  }

  // Delayed callback exists.
  if (new_output.callback().has_delay_millisec()) {
    message_queue->AddMessage(WM_IME_NOTIFY,
                              IMN_PRIVATE,
                              kNotifyDelayedCallback);
    return UpdateContextMain(himc, next_state, new_output, message_queue);
  }

  // Immediate callback exists.
  const SessionCommand &callback_command =
      new_output.callback().session_command();

  // Callback of CONVERT_REVERSE is an exception.
  // We ignore all other fields in |callback_command| in this case.
  // The UI handler will invoke reconversion later as other Japanese IMEs do.
  if (callback_command.has_type() &&
      callback_command.type() == SessionCommand::CONVERT_REVERSE) {
    if (message_queue != nullptr) {
      message_queue->AddMessage(WM_IME_NOTIFY, IMN_PRIVATE,
                                kNotifyReconvertFromIME);
    }
    return true;
  }

  // Otherwise, use |callback_output| and |callback_state| instead of
  // |new_output| and |next_mode|, respectively.
  UIContext context(himc);
  Output callback_output;
  if (!context.client()->SendCommand(callback_command, &callback_output)) {
    return false;
  }
  InputState callback_state;
  if (!GetNextState(himc, callback_output, &callback_state)) {
    return false;
  }
  return UpdateContextMain(himc, callback_state,
                           callback_output, message_queue);
}

bool ImeCore::UpdateContextMain(HIMC himc,
                                const InputState &next_state,
                                const commands::Output &new_output,
                                MessageQueue *message_queue) {
  DCHECK(IsInputContextInitialized(himc));
  const bool generate_message = (message_queue != nullptr);
  ScopedHIMC<InputContext> context(himc);
  ScopedHIMCC<PrivateContext> private_context(context->hPrivate);

  // If the deletion range matches commands::Capability::DELETE_PRECEDING_TEXT,
  // initialize the deleter.
  if (generate_message &&
      new_output.has_consumed() && new_output.has_deletion_range() &&
      new_output.deletion_range().has_length() &&
      new_output.deletion_range().has_offset() &&
      (new_output.deletion_range().length() ==
       -new_output.deletion_range().offset())) {
    // If there remains an ongoing composition, it should be cleared before
    // VK_BACKs are delivered.  (b/3423449)
    UIContext uicontext(himc);
    if (!uicontext.IsCompositionStringEmpty()) {
      commands::Output empty_output;
      if (!UpdateCompositionStringAndPushMessages(
              himc, empty_output, message_queue)) {
        return false;
      }
    }

    // Make sure the pending output does not have |deletion_range|.
    // Otherwise, an infinite loop will be created.
    commands::Output output;
    output.CopyFrom(new_output);
    output.clear_deletion_range();
    private_context->deleter->BeginDeletion(
        new_output.deletion_range().length(), output, next_state);
    return true;
  }

  if (new_output.has_consumed()) {
    private_context->last_output->CopyFrom(new_output);
  }

  *private_context->ime_state = next_state;
  const bool previous_open = (context->fOpen != FALSE);
  const DWORD previous_conversion = context->fdwConversion;
  const commands::Output &output =
      *private_context->last_output;

  // Update context.
  context->fOpen = next_state.open ? TRUE : FALSE;
  context->fdwConversion = next_state.logical_conversion_mode;

  vector<UIMessage> composition_messages;
  if (!UpdateCompositionString(himc, output, &composition_messages)) {
    return false;
  }

  vector<UIMessage> candidate_messages;
  context->hCandInfo =
      mozc::win32::CandidateInfoUtil::Update(context->hCandInfo,
                                             output, &candidate_messages);
  if (context->hCandInfo == nullptr) {
    return false;
  }

  if (generate_message) {
    // In order to minimize the risk of application compatibility problem,
    // we might want to send these messages in the the same order to MS-IME.
    // See b/3488848 for details.
    vector<UIMessage> sorted_messages;
    SortIMEMessages(composition_messages,
                    candidate_messages,
                    previous_open,
                    previous_conversion,
                    next_state.open,
                    next_state.logical_conversion_mode,
                    &sorted_messages);

    // Allow visibility trackers to track if each UI message will be
    UIVisibilityTracker *ui_visibility_tracker =
        private_context->ui_visibility_tracker;
    for (vector<UIMessage>::const_iterator it = sorted_messages.begin();
         it != sorted_messages.end(); ++it) {
      if (UIVisibilityTracker::IsVisibilityTestMessageForCandidateWindow(
             it->message(), it->wparam(), it->lparam())) {
       ui_visibility_tracker->BeginVisibilityTestForCandidateWindow();
      }
      if (UIVisibilityTracker::IsVisibilityTestMessageForComposiwionWindow(
             it->message(), it->wparam(), it->lparam())) {
        ui_visibility_tracker->BeginVisibilityTestForCompositionWindow();
      }
      message_queue->AddMessage(it->message(), it->wparam(), it->lparam());
    }
  }

  return true;
}

BOOL ImeCore::IMEOff(HIMC himc, bool generate_message) {
  if (!IsInputContextInitialized(himc)) {
    return FALSE;
  }

  mozc::win32::UIContext context(himc);

  DWORD logical_conversion_mode = 0;
  if (!context.GetLogicalConversionMode(&logical_conversion_mode)) {
    return FALSE;
  }

  commands::Output output;
  if (!ImeCore::CloseIME(context.client(), logical_conversion_mode,
                         &output)) {
    return FALSE;
  }
  bool next_open_status = false;
  DWORD next_logical_mode = 0;
  DWORD next_visible_mode = 0;
  if (!output.has_status()) {
    mozc::win32::UIContext uicontext(himc);
    if (!uicontext.GetConversionMode(&next_logical_mode)) {
      return FALSE;
    }
    next_visible_mode = next_logical_mode;
  } else if (!mozc::win32::ConversionModeUtil::
                  ConvertStatusFromMozcToNative(
      output.status(), context.IsKanaInputPreferred(),
      &next_open_status, &next_logical_mode, &next_visible_mode)) {
    return FALSE;
  }
  InputState next_state;
  next_state.open = false;  // We ignore the returned status.
  next_state.logical_conversion_mode = next_logical_mode;
  next_state.visible_conversion_mode = next_visible_mode;
  if (!generate_message) {
    if (!UpdateContext(himc, next_state, output, nullptr)) {
      return FALSE;
    }
    return TRUE;
  }

  MessageQueue message_queue(himc);
  if (!UpdateContext(himc, next_state, output, &message_queue)) {
    return FALSE;
  }
  return (message_queue.Send() ? TRUE : FALSE);
}

BOOL ImeCore::HighlightCandidate(
    HIMC himc, int32 candidate_index, bool generate_message) {
  if (!IsInputContextInitialized(himc)) {
    return FALSE;
  }

  UIContext context(himc);
  if (context.IsEmpty()) {
    return FALSE;
  }

  int32 next_candidate_id = 0;
  {
    commands::Output last_output;
    if (!context.GetLastOutput(&last_output)) {
      return FALSE;
    }

    if (!OutputUtil::GetCandidateIdByIndex(
             last_output, candidate_index, &next_candidate_id)) {
      return FALSE;
    }

    // Stop sending HIGHLIGHT_CANDIDATE if the given candidate is already
    // selected.  If the |last_output| does not have focused candidate,
    // HIGHLIGHT_CANDIDATE is always be sent.
    int32 focused_candidate_id = 0;
    if (OutputUtil::GetFocusedCandidateId(
            last_output, &focused_candidate_id) &&
        (next_candidate_id == focused_candidate_id)) {
      // Already highlighted.
      return TRUE;
    }
  }

  commands::Output output;
  // TODO(yukawa, komatsu): Make a function in client dir.
  {
    mozc::commands::SessionCommand command;
    command.set_type(mozc::commands::SessionCommand::HIGHLIGHT_CANDIDATE);
    command.set_id(next_candidate_id);
    if (!context.client()->SendCommand(command, &output)) {
      return FALSE;
    }
  }

  return UpdateInputContext(himc, output, generate_message);
}

BOOL ImeCore::CloseCandidate(HIMC himc, bool generate_message) {
  if (!IsInputContextInitialized(himc)) {
    return FALSE;
  }

  UIContext context(himc);
  if (context.IsEmpty()) {
    return FALSE;
  }

  int32 focused_candidate_id = 0;
  {
    commands::Output last_output;
    if (!context.GetLastOutput(&last_output)) {
      return FALSE;
    }

    if (!last_output.has_all_candidate_words()) {
      // already closed.
      return TRUE;
    }

    // Although we should not handle CloseCandidate when a suggest window is
    // displayed, currently we need this path to support mouse clicking for
    // suggest window.

    if (!OutputUtil::GetFocusedCandidateId(
             last_output, &focused_candidate_id)) {
      return FALSE;
    }
  }

  commands::Output output;
  // TODO(yukawa, komatsu): Make a function in client dir.
  {
    mozc::commands::SessionCommand command;
    command.set_type(mozc::commands::SessionCommand::SELECT_CANDIDATE);
    command.set_id(focused_candidate_id);
    if (!context.client()->SendCommand(command, &output)) {
      return FALSE;
    }
  }

  return UpdateInputContext(himc, output, generate_message);
}

bool ImeCore::IsActiveContext(HIMC himc) {
  bool is_active = false;
  const HWND focus_window = ::GetFocus();
  if (focus_window != nullptr &&
      ::IsWindow(focus_window) != FALSE) {
    const HIMC active_himc = ::ImmGetContext(focus_window);
    is_active = (himc == active_himc);
    ::ImmReleaseContext(focus_window, active_himc);
  }
  return is_active;
}

bool ImeCore::TurnOnIMEAndTryToReconvertFromIME(HIMC himc) {
  UIContext context(himc);
  if (context.IsEmpty()) {
    return false;
  }
  if (context.input_context() == nullptr) {
    return false;
  }
  if (!context.IsCompositionStringEmpty()) {
    // TODO(yukawa): Use Mozc server to determine the behavior when any
    //   appropriate protocol becomes available.
    DLOG(INFO) << "Ongoing composition exists.";
    return false;
  }

  const string &text_utf8 = GetTextForReconversionFromIME(himc);
  if (text_utf8.empty()) {
    if (context.GetOpenStatus()) {
      return true;
    }
    // Currently Mozc server will not turn on IME when |text_utf8| is empty but
    // people expect IME will be turned on even when the reconversion does
    // nothing.  b/4225148.
    return (::ImmSetOpenStatus(himc, TRUE) != FALSE);
  }

  commands::Output output;
  {
    mozc::commands::SessionCommand command;
    command.set_type(mozc::commands::SessionCommand::CONVERT_REVERSE);
    command.set_text(text_utf8);
    if (!context.client()->SendCommand(command, &output)) {
      LOG(ERROR) << "SendCommand failed.";
      return false;
    }
  }

  return UpdateInputContext(himc, output, true);
}

string ImeCore::GetTextForReconversionFromIME(HIMC himc) {
  // Implementation Note:
  // In order to implement IMM32 reconversion, IME is responsible to update
  // the following fields in RECONVERTSTRING.
  // - dwCompStrLen
  // - dwCompStrOffset
  // - dwTargetStrOffset
  // - dwTargetStrLen
  // However, current Mozc server supports only "pre-segmented" reconversion.
  // So the IME module assumes that the entire range pointed by
  // |RECONVERTSTRING::dwTargetStrOffset| and |RECONVERTSTRING::dwTargetStrLen|
  // is to be reconverted.  Technically most of the following processes should
  // be done at the server-side.
  LRESULT result = ::ImmRequestMessageW(himc, IMR_RECONVERTSTRING, 0);
  if (result == 0) {
    DLOG(INFO) << "IMR_RECONVERTSTRING is not supported.";
    return "";
  }

  const size_t buffer_size = static_cast<size_t>(result);
  if (buffer_size > kReconvertStringSizeLimit) {
    LOG(ERROR) << "Too large RECONVERTSTRING.";
    return "";
  }

  unique_ptr<BYTE[]> buffer(new BYTE[buffer_size]);

  RECONVERTSTRING *reconvert_string =
      reinterpret_cast<RECONVERTSTRING *>(buffer.get());
  reconvert_string->dwSize = buffer_size;
  reconvert_string->dwVersion = 0;

  result = ::ImmRequestMessageW(himc, IMR_RECONVERTSTRING,
                                reinterpret_cast<LPARAM>(reconvert_string));
  if (result == 0) {
    DLOG(ERROR) << "RECONVERTSTRING is nullptr.";
    return "";
  }

  unique_ptr<BYTE[]> copied_buffer(new BYTE[buffer_size]);
  for (size_t i = 0; i < buffer_size; ++i) {
    copied_buffer[i] = buffer[i];
  }
  RECONVERTSTRING *expanded_reconvert_string =
      reinterpret_cast<RECONVERTSTRING *>(copied_buffer.get());

  // Expand the composition range if necessary.
  if (!ReconvertString::EnsureCompositionIsNotEmpty(
          expanded_reconvert_string)) {
    return "";
  }
  result = ::ImmRequestMessageW(
      himc, IMR_CONFIRMRECONVERTSTRING,
      reinterpret_cast<LPARAM>(expanded_reconvert_string));
  if (result != FALSE) {
    // The application accepted |expanded_reconvert_string|.
    reconvert_string = expanded_reconvert_string;
  }

  string total_composition_utf8;
  if (!GetReconvertString(reconvert_string, &total_composition_utf8)) {
    return "";
  }

  return total_composition_utf8;
}

bool ImeCore::QueryReconversionFromApplication(
    HIMC himc, RECONVERTSTRING *composition_info,
    RECONVERTSTRING *reading_info) {
  // Currently, we are ignoring |reading_info|.
  // TODO(yukawa): Support |reading_info|.

  if (!ReconvertString::EnsureCompositionIsNotEmpty(composition_info)) {
    return false;
  }

  string total_composition_utf8;
  if (!GetReconvertString(composition_info, &total_composition_utf8)) {
    return false;
  }

  return true;
}

bool ImeCore::ReconversionFromApplication(
    HIMC himc, const RECONVERTSTRING *composition_info,
    const RECONVERTSTRING *reading_info) {
  // Currently, we are ignoring |reading_info|.
  // TODO(yukawa): Support |reading_info|.

  UIContext context(himc);
  if (context.IsEmpty()) {
    return false;
  }
  if (context.input_context() == nullptr) {
    return false;
  }

  if (!context.IsCompositionStringEmpty()) {
    // TODO(yukawa): Use Mozc server to determine the behavior when any
    //   appropriate protocol becomes available.
    DLOG(INFO) << "Ongoing composition exists.";
    return false;
  }

  if (composition_info->dwCompStrLen == 0) {
    // There is no text selection. Reconversion cannot be started.
    return false;
  }

  string total_composition_utf8;
  if (!GetReconvertString(composition_info, &total_composition_utf8)) {
    return false;
  }

  commands::Output output;
  mozc::commands::SessionCommand command;
  command.set_type(mozc::commands::SessionCommand::CONVERT_REVERSE);
  command.set_text(total_composition_utf8);
  if (!context.client()->SendCommand(command, &output)) {
    LOG(ERROR) << "SendCommand failed.";
    return false;
  }

  return UpdateInputContext(himc, output, true);
}

}  // namespace win32
}  // namespace mozc
