// 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/tip/tip_edit_session.h"

#include <Windows.h>

#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _WTL_NO_AUTOMATIC_NAMESPACE
// Workaround against KB813540
#include <atlbase_mozc.h>
#include <atlcom.h>

#include <string>

#include "base/util.h"
#include "client/client_interface.h"
#include "session/commands.pb.h"
#include "win32/base/conversion_mode_util.h"
#include "win32/base/deleter.h"
#include "win32/base/input_state.h"
#include "win32/tip/tip_composition_util.h"
#include "win32/tip/tip_edit_session_impl.h"
#include "win32/tip/tip_input_mode_manager.h"
#include "win32/tip/tip_private_context.h"
#include "win32/tip/tip_ref_count.h"
#include "win32/tip/tip_range_util.h"
#include "win32/tip/tip_status.h"
#include "win32/tip/tip_surrounding_text.h"
#include "win32/tip/tip_text_service.h"
#include "win32/tip/tip_thread_context.h"
#include "win32/tip/tip_ui_handler.h"

namespace mozc {
namespace win32 {
namespace tsf {

namespace {

using ::ATL::CComPtr;
using ::mozc::commands::Candidates;
using ::mozc::commands::DeletionRange;
using ::mozc::commands::KeyEvent;
using ::mozc::commands::Output;
using ::mozc::commands::SessionCommand;
typedef ::mozc::commands::Candidates_Candidate Candidate;
typedef ::mozc::commands::CompositionMode CompositionMode;
typedef ::mozc::commands::KeyEvent_SpecialKey SpecialKey;
typedef ::mozc::commands::SessionCommand::CommandType CommandType;
typedef ::mozc::commands::SessionCommand::UsageStatsEvent UsageStatsEvent;

HRESULT QueryInterfaceImpl(
    ITfEditSession *edit_session, REFIID interface_id, void **object) {
  if (!object) {
    return E_INVALIDARG;
  }

  // Find a matching interface from the ones implemented by this object.
  // This object implements IUnknown and ITfEditSession.
  if (::IsEqualIID(interface_id, IID_IUnknown)) {
    *object = static_cast<IUnknown *>(edit_session);
  } else if (IsEqualIID(interface_id, IID_ITfEditSession)) {
    *object = static_cast<ITfEditSession *>(edit_session);
  } else {
    *object = nullptr;
    return E_NOINTERFACE;
  }

  edit_session->AddRef();
  return S_OK;
}

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class AsyncLayoutChangeEditSessionImpl : public ITfEditSession {
 public:
  AsyncLayoutChangeEditSessionImpl(CComPtr<TipTextService> text_service,
                                   CComPtr<ITfContext> context)
    : text_service_(text_service),
      context_(context) {
  }
  ~AsyncLayoutChangeEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie read_cookie) {
    // Ignore the returned code as TipUiHandler::UpdateUI will be called
    // anyway.
    text_service_->GetThreadContext()->GetInputModeManager()->
        OnMoveFocusedWindow();

    TipEditSessionImpl::UpdateUI(text_service_, context_, read_cookie);
    return S_OK;
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfContext> context_;

  DISALLOW_COPY_AND_ASSIGN(AsyncLayoutChangeEditSessionImpl);
};

bool OnLayoutChangedAsyncImpl(TipTextService *text_service,
                              ITfContext *context) {
  if (context == nullptr) {
    return false;
  }

  if (context == nullptr) {
    return false;
  }

  CComPtr<ITfEditSession> edit_session(new AsyncLayoutChangeEditSessionImpl(
      text_service, context));

  HRESULT edit_session_result = S_OK;
  const HRESULT hr = context->RequestEditSession(
      text_service->GetClientID(),
      edit_session,
      TF_ES_ASYNCDONTCARE | TF_ES_READ,
      &edit_session_result);
  if (FAILED(hr)) {
    return false;
  }
  return SUCCEEDED(edit_session_result);
};

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class AsyncSetFocusEditSessionImpl : public ITfEditSession {
 public:
  AsyncSetFocusEditSessionImpl(CComPtr<TipTextService> text_service,
                               CComPtr<ITfContext> context)
    : text_service_(text_service),
      context_(context) {
  }
  ~AsyncSetFocusEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie read_cookie) {
    vector<InputScope> input_scopes;
    CComPtr<ITfRange> selection_range;
    TfActiveSelEnd active_sel_end = TF_AE_NONE;
    if (SUCCEEDED(TipRangeUtil::GetDefaultSelection(
            context_, read_cookie, &selection_range, &active_sel_end))) {
      TipRangeUtil::GetInputScopes(
          selection_range, read_cookie, &input_scopes);
    }
    ITfThreadMgr *thread_manager = text_service_->GetThreadManager();
    TipThreadContext *thread_context = text_service_->GetThreadContext();
    DWORD system_input_mode = 0;
    if (!TipStatus::GetInputModeConversion(thread_manager,
                                           text_service_->GetClientID(),
                                           &system_input_mode)) {
      return E_FAIL;
    }
    const auto action = thread_context->GetInputModeManager()->OnSetFocus(
        TipStatus::IsOpen(thread_manager), system_input_mode, input_scopes);
    if (action == TipInputModeManager::kUpdateUI) {
      TipEditSessionImpl::UpdateUI(text_service_, context_, read_cookie);
    }
    return S_OK;
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfContext> context_;

  DISALLOW_COPY_AND_ASSIGN(AsyncSetFocusEditSessionImpl);
};

bool OnUpdateOnOffModeAsync(TipTextService *text_service,
                            ITfContext *context,
                            bool open) {
  const auto action =text_service->GetThreadContext()->GetInputModeManager()->
      OnChangeOpenClose(open);
  if (action == TipInputModeManager::kUpdateUI) {
    return OnLayoutChangedAsyncImpl(text_service, context);
  }
  return true;
};

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class AsyncSwitchInputModeEditSessionImpl : public ITfEditSession {
 public:
  AsyncSwitchInputModeEditSessionImpl(CComPtr<TipTextService> text_service,
                                      CComPtr<ITfContext> context,
                                      bool open,
                                      uint32 native_mode)
      : text_service_(text_service),
        context_(context),
        open_(open),
        native_mode_(native_mode) {
  }
  ~AsyncSwitchInputModeEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie write_cookie) {
    TipPrivateContext *private_context =
      text_service_->GetPrivateContext(context_);
    if (!private_context) {
      // This is an unmanaged context. It's OK. Nothing to do.
      return S_OK;
    }

    const TipInputModeManager *input_mode_manager =
        text_service_->GetThreadContext()->GetInputModeManager();

    CompositionMode mozc_mode = commands::HIRAGANA;
    if (!ConversionModeUtil::ToMozcMode(native_mode_, &mozc_mode)) {
      return E_FAIL;
    }
    Output output;
    if (!open_) {
      // The next on/off mode is OFF. Send TURN_OFF_IME to update the converter
      // state.
      SessionCommand command;
      command.set_type(commands::SessionCommand::TURN_OFF_IME);
      command.set_composition_mode(mozc_mode);
      if (!private_context->GetClient()->SendCommand(command, &output)) {
        return E_FAIL;
      }
    } else if (!input_mode_manager->GetEffectiveOpenClose()) {
      // The next on/off mode is ON but the state of input mode manager is
      // OFF. Send TURN_ON_IME to update the converter state.
      SessionCommand command;
      command.set_type(commands::SessionCommand::TURN_ON_IME);
      command.set_composition_mode(mozc_mode);
      if (!private_context->GetClient()->SendCommand(command, &output)) {
        return E_FAIL;
      }
    } else {
      // The next on/off mode and the state of input mode manager is
      // consistent. Send SWITCH_INPUT_MODE to update the converter state.
      SessionCommand command;
      command.set_type(SessionCommand::SWITCH_INPUT_MODE);
      command.set_composition_mode(mozc_mode);
      if (!private_context->GetClient()->SendCommand(command, &output)) {
        return E_FAIL;
      }
    }
    return TipEditSessionImpl::UpdateContext(
        text_service_, context_, write_cookie, output);
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfContext> context_;
  bool open_;
  uint32 native_mode_;

  DISALLOW_COPY_AND_ASSIGN(AsyncSwitchInputModeEditSessionImpl);
};

bool OnSwitchInputModeAsync(TipTextService *text_service,
                            ITfContext *context,
                            bool open,
                            uint32 native_mode) {
  // When RequestEditSession fails, it does not maintain the reference count.
  // So we need to ensure that AddRef/Release should be called at least once
  // per object.
  CComPtr<ITfEditSession> edit_session(new AsyncSwitchInputModeEditSessionImpl(
      text_service, context, open, native_mode));

  HRESULT edit_session_result = S_OK;
  const HRESULT hr = context->RequestEditSession(
      text_service->GetClientID(),
      edit_session,
      TF_ES_ASYNCDONTCARE | TF_ES_READWRITE,
      &edit_session_result);
  if (FAILED(hr)) {
    return false;
  }
  return SUCCEEDED(edit_session_result);
};

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class AsyncSessionCommandEditSessionImpl : public ITfEditSession {
 public:
  AsyncSessionCommandEditSessionImpl(CComPtr<TipTextService> text_service,
                                     CComPtr<ITfContext> context,
                                     const SessionCommand &session_command)
      : text_service_(text_service),
        context_(context) {
    session_command_.CopyFrom(session_command);
  }
  ~AsyncSessionCommandEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie write_cookie) {
    Output output;
    TipPrivateContext *private_context =
        text_service_->GetPrivateContext(context_);
    if (private_context == nullptr) {
      return E_FAIL;
    }
    if (!private_context->GetClient()->SendCommand(session_command_, &output)) {
      return E_FAIL;
    }
    return TipEditSessionImpl::UpdateContext(
        text_service_, context_, write_cookie, output);
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfContext> context_;
  SessionCommand session_command_;

  DISALLOW_COPY_AND_ASSIGN(AsyncSessionCommandEditSessionImpl);
};

bool OnSessionCommandAsync(TipTextService *text_service,
                           ITfContext *context,
                           const SessionCommand &session_command) {
  // When RequestEditSession fails, it does not maintain the reference count.
  // So we need to ensure that AddRef/Release should be called at least once
  // per object.
  CComPtr<ITfEditSession> edit_session(new AsyncSessionCommandEditSessionImpl(
      text_service, context, session_command));

  HRESULT edit_session_result = S_OK;
  const HRESULT hr = context->RequestEditSession(
      text_service->GetClientID(),
      edit_session,
      TF_ES_ASYNCDONTCARE | TF_ES_READWRITE,
      &edit_session_result);
  if (FAILED(hr)) {
    return false;
  }
  return SUCCEEDED(edit_session_result);
};

bool TurnOnImeAndTryToReconvertFromIme(TipTextService *text_service,
                                       ITfContext *context) {
  if (context == nullptr) {
    return false;
  }

  TipSurroundingTextInfo info;
  bool need_async_edit_session = false;
  if (!TipSurroundingText::PrepareForReconversionFromIme(
          text_service, context, &info, &need_async_edit_session)) {
    return false;
  }

  // Currently this is not supported.
  if (info.in_composition) {
    return false;
  }

  string text_utf8;
  Util::WideToUTF8(info.selected_text, &text_utf8);
  if (text_utf8.empty()) {
    const bool open = text_service->GetThreadContext()->GetInputModeManager()->
        GetEffectiveOpenClose();
    if (open) {
      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 OnUpdateOnOffModeAsync(text_service, context, true);
  }

  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context. It's OK. Nothing to do.
    return true;
  }

  Output output;
  {
    SessionCommand command;
    command.set_type(SessionCommand::CONVERT_REVERSE);
    command.set_text(text_utf8);
    if (!private_context->GetClient()->SendCommand(command, &output)) {
      return false;
    }
  }

  if (output.has_callback() &&
      output.callback().has_session_command() &&
      output.callback().session_command().has_type()) {
    // do not allow recursive call.
    return false;
  }

  if (need_async_edit_session) {
    return TipEditSession::OnOutputReceivedAsync(text_service, context, output);
  } else {
    return TipEditSession::OnOutputReceivedSync(text_service, context, output);
  }
}

bool UndoCommint(TipTextService *text_service, ITfContext *context) {
  if (context == nullptr) {
    return false;
  }

  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context. It's OK. Nothing to do.
    return true;
  }

  Output output;
  {
    SessionCommand command;
    command.set_type(SessionCommand::UNDO);
    if (!private_context->GetClient()->SendCommand(command, &output)) {
      return false;
    }
  }

  if (!output.has_deletion_range()) {
    return false;
  }

  const DeletionRange &deletion_range = output.deletion_range();
  if (deletion_range.offset() > 0 ||
      -deletion_range.offset() != deletion_range.length()) {
    return false;
  }
  const size_t num_characters_to_be_deleted_ucs4 = -deletion_range.offset();
  if (!TipSurroundingText::DeletePrecedingText(
          text_service, context, num_characters_to_be_deleted_ucs4)) {
    // If TSF-based delete-preceding-text fails, use backspace forwarding as
    // a fall back.

    // Make sure the pending output does not have |deletion_range|.
    // Otherwise, an infinite loop will be created.
    Output pending_output;
    pending_output.CopyFrom(output);
    pending_output.clear_deletion_range();

    // actually |next_state| will be ignored in TSF Mozc.
    // So it is OK to pass the default value.
    InputState next_state;
    private_context->GetDeleter()->BeginDeletion(
        deletion_range.length(), pending_output, next_state);
    return true;
  }

  if (output.has_callback() &&
      output.callback().has_session_command() &&
      output.callback().session_command().has_type()) {
    // do not allow recursive call.
    return false;
  }

  // Undo commit should be called from and only from the key event handler.
  return TipEditSession::OnOutputReceivedSync(text_service, context, output);
}

bool IsCandidateFocused(const Output &output, uint32 candidate_id) {
  if (!output.has_candidates()) {
    return false;
  }
  const Candidates &candidates = output.candidates();

  if (!candidates.has_focused_index()) {
    return false;
  }
  const uint32 focused_index = candidates.focused_index();
  for (size_t i = 0; i < candidates.candidate_size(); ++i) {
    const Candidate &candidate = candidates.candidate(i);
    if (candidate.index() != focused_index) {
      continue;
    }
    if (candidate.id() == candidate_id) {
      return true;
    }
  }
  return false;
}

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class SyncEditSessionImpl : public ITfEditSession {
 public:
  SyncEditSessionImpl(CComPtr<TipTextService> text_service,
                      CComPtr<ITfContext> context,
                      const Output &output)
      : text_service_(text_service),
        context_(context) {
    output_.CopyFrom(output);
  }
  ~SyncEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie write_cookie) {
    return TipEditSessionImpl::UpdateContext(
        text_service_, context_, write_cookie, output_);
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfContext> context_;
  Output output_;

  DISALLOW_COPY_AND_ASSIGN(SyncEditSessionImpl);
};

enum EditSessionMode {
  kDontCare = 0,
  kAsync,
  kSync,
};

bool OnOutputReceivedImpl(TipTextService *text_service,
                          ITfContext *context,
                          const Output &new_output,
                          EditSessionMode mode) {
  if (new_output.has_callback() &&
      new_output.callback().has_session_command() &&
      new_output.callback().session_command().has_type()) {
    // Callback exists.
    const SessionCommand::CommandType &type =
        new_output.callback().session_command().type();
    switch (type) {
      case SessionCommand::CONVERT_REVERSE:
        return TurnOnImeAndTryToReconvertFromIme(text_service, context);
      case SessionCommand::UNDO:
        return UndoCommint(text_service, context);
    }
  }

  // When RequestEditSession fails, it does not maintain the reference count.
  // So we need to ensure that AddRef/Release should be called at least once
  // per object.
  CComPtr<ITfEditSession> edit_session(new SyncEditSessionImpl(
      text_service, context, new_output));

  DWORD edit_session_flag = TF_ES_READWRITE;
  switch (mode) {
    case kAsync:
      edit_session_flag |= TF_ES_ASYNC;
      break;
    case kSync:
      edit_session_flag |= TF_ES_SYNC;
      break;
    case kDontCare:
      edit_session_flag |= TF_ES_ASYNCDONTCARE;
      break;
    default:
      DCHECK(false) << "unknown mode: " << mode;
      break;
  }

  HRESULT edit_session_result = S_OK;
  const HRESULT hr = context->RequestEditSession(
      text_service->GetClientID(),
      edit_session,
      edit_session_flag,
      &edit_session_result);
  if (FAILED(hr)) {
    return false;
  }
  return SUCCEEDED(edit_session_result);
}

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class SyncGetTextEditSessionImpl : public ITfEditSession {
 public:
  SyncGetTextEditSessionImpl(TipTextService *text_service, ITfRange *range)
      : text_service_(text_service),
        range_(range) {
  }
  ~SyncGetTextEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie read_cookie) {
    TipRangeUtil::GetText(range_, read_cookie, &text_);
    return S_OK;
  }

  const wstring &text() const {
    return text_;
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfRange> range_;
  wstring text_;

  DISALLOW_COPY_AND_ASSIGN(SyncGetTextEditSessionImpl);
};

// This class is an implementation class for the ITfEditSession classes, which
// is an observer for exclusively updating the text store of a TSF thread
// manager.
class AsyncSetTextEditSessionImpl : public ITfEditSession {
 public:
  AsyncSetTextEditSessionImpl(TipTextService *text_service,
                              const wstring &text,
                              ITfRange *range)
      : text_service_(text_service),
        text_(text),
        range_(range) {
  }
  ~AsyncSetTextEditSessionImpl() {}

  // The IUnknown interface methods.
  STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    return QueryInterfaceImpl(this, interface_id, object);
  }

  STDMETHODIMP_(ULONG) AddRef() {
    return ref_count_.AddRefImpl();
  }

  STDMETHODIMP_(ULONG) Release() {
    const ULONG count = ref_count_.ReleaseImpl();
    if (count == 0) {
      delete this;
    }
    return count;
  }

  // The ITfEditSession interface method.
  // This function is called back by the TSF thread manager when an edit
  // request is granted.
  virtual STDMETHODIMP DoEditSession(TfEditCookie write_cookie) {
    range_->SetText(write_cookie, 0, text_.data(), text_.size());
    return S_OK;
  }

 private:
  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  const wstring text_;
  CComPtr<ITfRange> range_;

  DISALLOW_COPY_AND_ASSIGN(AsyncSetTextEditSessionImpl);
};

}  // namespace

bool TipEditSession::OnOutputReceivedSync(TipTextService *text_service,
                                          ITfContext *context,
                                          const Output &new_output) {
  return OnOutputReceivedImpl(text_service, context, new_output, kSync);
}

bool TipEditSession::OnOutputReceivedAsync(TipTextService *text_service,
                                           ITfContext *context,
                                           const Output &new_output) {
  return OnOutputReceivedImpl(text_service, context, new_output, kAsync);
}

bool TipEditSession::OnLayoutChangedAsync(
    TipTextService *text_service, ITfContext *context) {
  return OnLayoutChangedAsyncImpl(text_service, context);
}

bool TipEditSession::OnSetFocusAsync(TipTextService *text_service,
                                     ITfDocumentMgr *document_manager) {
  if (document_manager == nullptr) {
    TipUiHandler::OnFocusChange(text_service, nullptr);
    return true;
  }

  CComPtr<ITfContext> context;
  if (FAILED(document_manager->GetBase(&context))) {
    return false;
  }

  // When RequestEditSession fails, it does not maintain the reference count.
  // So we need to ensure that AddRef/Release should be called at least once
  // per object.
  CComPtr<ITfEditSession> edit_session(new AsyncSetFocusEditSessionImpl(
      text_service, context));

  HRESULT edit_session_result = S_OK;
  const HRESULT hr = context->RequestEditSession(
      text_service->GetClientID(),
      edit_session,
      TF_ES_ASYNCDONTCARE | TF_ES_READ,
      &edit_session_result);
  if (FAILED(hr)) {
    return false;
  }
  return SUCCEEDED(edit_session_result);
}

bool TipEditSession::OnModeChangedAsync(TipTextService *text_service) {
  ITfThreadMgr *thread_mgr = text_service->GetThreadManager();
  if (thread_mgr == nullptr) {
    return false;
  }

  CComPtr<ITfDocumentMgr> document_manager;
  if (FAILED(thread_mgr->GetFocus(&document_manager))) {
    return false;
  }
  if (document_manager == nullptr) {
    // This is an unmanaged context. It's OK. Nothing to do.
    return true;
  }

  CComPtr<ITfContext> context;
  if (FAILED(document_manager->GetBase(&context))) {
    return false;
  }
  DWORD native_mode = false;
  if (!TipStatus::GetInputModeConversion(
          text_service->GetThreadManager(),
          text_service->GetClientID(),
          &native_mode)) {
    return false;
  }
  const auto action = text_service->GetThreadContext()->GetInputModeManager()->
      OnChangeConversionMode(native_mode);
  if (action == TipInputModeManager::kUpdateUI) {
      return OnLayoutChangedAsyncImpl(text_service, context);
  }
  return true;
}

bool TipEditSession::OnOpenCloseChangedAsync(TipTextService *text_service) {
  CComPtr<ITfDocumentMgr> document_manager;
  if (FAILED(text_service->GetThreadManager()->GetFocus(&document_manager))) {
    return false;
  }
  if (document_manager == nullptr) {
    // This is an unmanaged context. It's OK. Nothing to do.
    return true;
  }

  CComPtr<ITfContext> context;
  if (FAILED(document_manager->GetBase(&context))) {
    return false;
  }
  return OnUpdateOnOffModeAsync(
      text_service,
      context,
      TipStatus::IsOpen(text_service->GetThreadManager()));
}

bool TipEditSession::OnRendererCallbackAsync(TipTextService *text_service,
                                             ITfContext *context,
                                             WPARAM wparam,
                                             LPARAM lparam) {
  const CommandType type = static_cast<CommandType>(wparam);
  switch (type) {
    case SessionCommand::HIGHLIGHT_CANDIDATE:
    case SessionCommand::SELECT_CANDIDATE: {
      const int32 candidate_id = static_cast<int32>(lparam);
      TipPrivateContext *private_context =
          text_service->GetPrivateContext(context);
      if (private_context == nullptr) {
        return false;
      }
      if ((type == SessionCommand::HIGHLIGHT_CANDIDATE) &&
          IsCandidateFocused(private_context->last_output(), candidate_id)) {
        // Already focused. Nothing to do.
        return true;
      }

      SessionCommand command;
      command.set_type(type);
      command.set_id(candidate_id);
      return OnSessionCommandAsync(text_service, context, command);
    }
    case SessionCommand::USAGE_STATS_EVENT: {
      const UsageStatsEvent event_id = static_cast<UsageStatsEvent>(lparam);
      TipPrivateContext *private_context =
          text_service->GetPrivateContext(context);
      if (private_context == nullptr) {
        return false;
      }
      SessionCommand command;
      command.set_type(type);
      command.set_usage_stats_event(event_id);
      Output output_ignored;  // Discard the response in this case.
      if (!private_context->GetClient()->SendCommand(
              command, &output_ignored)) {
        return false;
      }
      return true;
    }
    default:
      return false;
  }
}

bool TipEditSession::SubmitAsync(TipTextService *text_service,
                                 ITfContext *context) {
  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context.
    return false;
  }

  SessionCommand session_command;
  session_command.set_type(SessionCommand::SUBMIT);
  return OnSessionCommandAsync(text_service, context, session_command);
}

bool TipEditSession::CancelCompositionAsync(
    TipTextService *text_service, ITfContext *context) {
  SessionCommand command;
  command.set_type(SessionCommand::REVERT);
  return OnSessionCommandAsync(text_service, context, command);
}

bool TipEditSession::HilightCandidateAsync(TipTextService *text_service,
                                           ITfContext *context,
                                           int candidate_id) {
  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context.
    return false;
  }

  SessionCommand session_command;
  session_command.set_type(SessionCommand::HIGHLIGHT_CANDIDATE);
  session_command.set_id(candidate_id);
  return OnSessionCommandAsync(text_service, context, session_command);
}

bool TipEditSession::SelectCandidateAsync(TipTextService *text_service,
                                          ITfContext *context,
                                          int candidate_id) {
  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context.
    return false;
  }

  SessionCommand session_command;
  session_command.set_type(SessionCommand::SELECT_CANDIDATE);
  session_command.set_id(candidate_id);
  return OnSessionCommandAsync(text_service, context, session_command);
}

bool TipEditSession::ReconvertFromApplicationSync(TipTextService *text_service,
                                                  ITfRange *range) {
  if (range == nullptr) {
    return false;
  }
  CComPtr<ITfContext> context;
  if (FAILED(range->GetContext(&context))) {
    return false;
  }
  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context.
    return false;
  }

  TipSurroundingTextInfo info;
  if (!TipSurroundingText::Get(text_service, context, &info)) {
    return false;
  }

  if (info.selected_text.empty()) {
    // Selected text is empty. Nothing to do.
    return false;
  }

  if (info.in_composition) {
    // on-going composition is found.
    return false;
  }

  // Stop reconversion when any embedded object is found because we cannot
  // easily restore it. See b/3406434
  if (info.selected_text.find(static_cast<wchar_t>(TS_CHAR_EMBEDDED)) !=
      wstring::npos) {
    // embedded object is found.
    return false;
  }

  SessionCommand command;
  command.set_type(SessionCommand::CONVERT_REVERSE);

  string text_utf8;
  Util::WideToUTF8(info.selected_text, &text_utf8);
  command.set_text(text_utf8);
  Output output;
  if (!private_context->GetClient()->SendCommand(command, &output)) {
    return false;
  }
  return OnOutputReceivedSync(text_service, context, output);
}

bool TipEditSession::SwitchInputModeAsync(TipTextService *text_service,
                                          uint32 mozc_mode) {
  commands::CompositionMode mode =
      static_cast<commands::CompositionMode>(mozc_mode);

  if (text_service == nullptr) {
    return false;
  }
  ITfThreadMgr *thread_mgr = text_service->GetThreadManager();
  if (thread_mgr == nullptr) {
    return false;
  }

  CComPtr<ITfDocumentMgr> document;
  if (FAILED(thread_mgr->GetFocus(&document))) {
    return false;
  }
  if (document == nullptr) {
    // This is an unmanaged context. It's OK. Nothing to do.
    return true;
  }

  CComPtr<ITfContext> context;
  if (FAILED(document->GetBase(&context))) {
    return false;
  }

  Output output;
  if (mode == commands::DIRECT) {
    DWORD native_mode = 0;
    if (!TipStatus::GetInputModeConversion(text_service->GetThreadManager(),
                                           text_service->GetClientID(),
                                           &native_mode)) {
      return false;
    }
    return OnSwitchInputModeAsync(text_service, context, false, native_mode);
  }
  TipPrivateContext *private_context = text_service->GetPrivateContext(context);
  if (!private_context) {
    // This is an unmanaged context.
    return false;
  }

  uint32 native_mode = 0;
  if (!ConversionModeUtil::ToNativeMode(
          mode, private_context->input_behavior().prefer_kana_input,
          &native_mode)) {
    return false;
  }

  return OnSwitchInputModeAsync(text_service, context, true, native_mode);
}

bool TipEditSession::GetTextSync(TipTextService *text_service,
                                 ITfRange *range,
                                 wstring *text) {
  CComPtr<ITfContext> context;
  if (FAILED(range->GetContext(&context))) {
    return false;
  }
  CComPtr<SyncGetTextEditSessionImpl> get_text(
      new SyncGetTextEditSessionImpl(text_service, range));

  HRESULT hr = S_OK;
  HRESULT hr_session = S_OK;
  hr = context->RequestEditSession(text_service->GetClientID(),
                                   get_text,
                                   TF_ES_SYNC | TF_ES_READ,
                                   &hr_session);
  if (FAILED(hr)) {
    return false;
  }
  *text = get_text->text();
  return true;
}

// static
bool TipEditSession::SetTextAsync(TipTextService *text_service,
                                  const wstring &text,
                                  ITfRange *range) {
  CComPtr<ITfContext> context;
  if (FAILED(range->GetContext(&context))) {
    return false;
  }
  CComPtr<AsyncSetTextEditSessionImpl> set_text(
      new AsyncSetTextEditSessionImpl(text_service, text, range));

  HRESULT hr = S_OK;
  HRESULT hr_session = S_OK;
  hr = context->RequestEditSession(text_service->GetClientID(),
                                   set_text,
                                   TF_ES_ASYNCDONTCARE | TF_ES_READWRITE,
                                   &hr_session);
  if (FAILED(hr)) {
    return false;
  }
  return true;
}

}  // namespace tsf
}  // namespace win32
}  // namespace mozc
