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

#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _WTL_NO_AUTOMATIC_NAMESPACE
#include <atlbase.h>
#include <atlcom.h>
#include <atlapp.h>
#include <atlmisc.h>
#include <atlstr.h>
#include <atlwin.h>
#include <msctf.h>

#include <memory>

#include "base/hash_tables.h"
#include "base/util.h"
#include "renderer/table_layout.h"
#include "renderer/win32/text_renderer.h"
#include "renderer/win32/win32_renderer_util.h"
#include "renderer/window_util.h"
#include "session/commands.pb.h"
#include "win32/tip/tip_composition_util.h"
#include "win32/tip/tip_dll_module.h"
#include "win32/tip/tip_edit_session.h"
#include "win32/tip/tip_private_context.h"
#include "win32/tip/tip_range_util.h"
#include "win32/tip/tip_ref_count.h"
#include "win32/tip/tip_text_service.h"
#include "win32/tip/tip_ui_element_delegate.h"
#include "win32/tip/tip_ui_handler_immersive.h"
#include "win32/tip/tip_ui_renderer_immersive.h"

namespace mozc {
namespace win32 {
namespace tsf {

namespace {

using ATL::CComPtr;
using ATL::CWindow;
using WTL::CBitmap;
using WTL::CBitmapHandle;
using WTL::CDC;
using WTL::CPaintDC;
using WTL::CPoint;
using WTL::CRect;
using WTL::CSize;

using ::mozc::commands::Candidates;
using ::mozc::commands::Output;
using ::mozc::commands::Preedit;
using ::mozc::renderer::TableLayout;
using ::mozc::renderer::WindowUtil;
using ::std::unique_ptr;

typedef ::mozc::commands::Candidates::Candidate Candidate;
typedef ::mozc::commands::Preedit_Segment Segment;
typedef ::mozc::commands::Preedit_Segment::Annotation Annotation;

#ifdef GOOGLE_JAPANESE_INPUT_BUILD

const wchar_t kImmersiveUIWindowClassName[] =
    L"Google Japanese Input Immersive UI Window";

#else

const wchar_t kImmersiveUIWindowClassName[] = L"Mozc Immersive UI Window";

#endif  // GOOGLE_JAPANESE_INPUT_BUILD

#ifndef EVENT_OBJECT_IME_SHOW
#define EVENT_OBJECT_IME_SHOW    0x8027
#define EVENT_OBJECT_IME_HIDE    0x8028
#define EVENT_OBJECT_IME_CHANGE  0x8029
#endif  // EVENT_OBJECT_IME_SHOW

// Represents the module handle of this module.
volatile HMODULE g_module = nullptr;

// True if the the DLL received DLL_PROCESS_DETACH notification.
volatile bool g_module_unloaded = false;

// Thread Local Storage (TLS) index to specify the current UI thread is
// initialized or not. If ::GetTlsValue(g_tls_index) returns non-zero
// value, the current thread is initialized.
volatile DWORD g_tls_index = TLS_OUT_OF_INDEXES;

struct RenderingInfo {
  CRect target_rect;
  Output output;
  bool has_target_rect;
  RenderingInfo()
      : has_target_rect(false) {
  }
};

size_t GetTargetPos(const commands::Output &output) {
  if (!output.has_candidates() || !output.candidates().has_category()) {
    return 0;
  }
  switch (output.candidates().category()) {
    case commands::PREDICTION:
    case commands::SUGGESTION:
      return 0;
    case commands::CONVERSION: {
        const Preedit &preedit = output.preedit();
        size_t offset = 0;
        for (int i = 0; i < preedit.segment_size(); ++i) {
          const Segment &segment = preedit.segment(i);
          const Annotation &annotation = segment.annotation();
          if (annotation == Segment::HIGHLIGHT) {
            return offset;
          }
          offset += Util::WideCharsLen(segment.value());
        }
        return offset;
      }
    default:
      return 0;
  }
}

// This function updates RendererCommand::CharacterPosition to emulate
// IMM32-based client. Ideally we'd better to define new field for TSF Mozc
// into which the result of ITfContextView::GetTextExt is stored.
bool FillRenderInfo(TipTextService *text_service,
                    ITfContext *context,
                    TfEditCookie read_cookie,
                    RenderingInfo *info) {
  TipPrivateContext *private_context =
      text_service->GetPrivateContext(context);
  if (private_context == nullptr) {
    return false;
  }

  info->output.Clear();
  info->target_rect = CRect();
  info->has_target_rect = false;
  const Output &output = private_context->last_output();

  CComPtr<ITfCompositionView> composition_view =
      TipCompositionUtil::GetComposition(context, read_cookie);
  if (!composition_view) {
    return false;
  }

  CComPtr<ITfRange> composition_range;
  if (FAILED(composition_view->GetRange(&composition_range))) {
    return false;
  }
  if (!composition_range) {
    return false;
  }

  CComPtr<ITfRange> target_range;
  if (FAILED(composition_range->Clone(&target_range))) {
    return false;
  }

  if (FAILED(target_range->Collapse(read_cookie, TF_ANCHOR_START))) {
    return false;
  }

  {
    const size_t target_pos = GetTargetPos(output);
    LONG shifted = 0;
    if (FAILED(target_range->ShiftStart(
            read_cookie, target_pos, &shifted, nullptr))) {
      return false;
    }
    if (FAILED(target_range->ShiftEnd(
            read_cookie, target_pos + 1, &shifted, nullptr))) {
      return false;
    }
  }

  CComPtr<ITfContextView> context_view;
  if (FAILED(context->GetActiveView(&context_view)) || !context_view) {
    return false;
  }

  RECT document_rect = {};
  if (FAILED(context_view->GetScreenExt(&document_rect))) {
    return false;
  }

  RECT text_rect = {};
  bool clipped = false;
  const HRESULT hr = TipRangeUtil::GetTextExt(
      context_view, read_cookie, target_range, &text_rect, &clipped);
  if (SUCCEEDED(hr)) {
    info->target_rect = text_rect;
    info->has_target_rect = true;
  } else if (hr == TF_E_NOLAYOUT) {
    // This is not a fatal error but |text_rect| is not available yet.
  } else {
    return false;
  }
  info->output.CopyFrom(output);
  return true;
}

CRect ToCRect(const Rect &rect) {
  return WTL::CRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
}

// Returns the smallest index of the given candidate list which satisfies
// candidates.candidate(i) == |candidate_index|.
// This function returns the size of the given candidate list when there
// aren't any candidates satisfying the above condition.
int GetCandidateArrayIndexByCandidateIndex(const Candidates &candidates,
                                           int candidate_index) {
  for (size_t i = 0; i < candidates.candidate_size(); ++i) {
    const Candidate &candidate = candidates.candidate(i);
    if (candidate.index() == candidate_index) {
      return i;
    }
  }
  return candidates.candidate_size();
}

// Returns the smallest index of the given candidate list which satisfies
// |candidates.focused_index| == |candidates.candidate(i).index()|.
// This function returns the size of the given candidate list when there
// aren't any candidates satisfying the above condition.
int GetFocusedArrayIndex(const Candidates &candidates) {
  const int kInvalidIndex = candidates.candidate_size();

  if (!candidates.has_focused_index()) {
    return kInvalidIndex;
  }

  const int focused_index = candidates.focused_index();

  return GetCandidateArrayIndexByCandidateIndex(candidates, focused_index);
}

class TipImmersiveUiElementImpl : public ITfCandidateListUIElementBehavior {
 public:
  TipImmersiveUiElementImpl(TipTextService *text_service,
                            ITfContext *context,
                            HWND window_handle)
      : text_service_(text_service),
        context_(context),
        delegate_(TipUiElementDelegateFactory::Create(
            text_service, context,
            TipUiElementDelegateFactory::kImmersiveCandidateWindow)),
        working_area_(renderer::win32::WorkingAreaFactory::Create()),
        text_renderer_(renderer::win32::TextRenderer::Create()),
        window_(window_handle),
        window_visible_(false) {
  }

  // Destructor is kept as non-virtual because this class is designed to be
  // destroyed only by "delete this" in Release() method.
  // TODO(yukawa): put "final" keyword to the class declaration when C++11
  //     is allowed.
  ~TipImmersiveUiElementImpl() {
  }

  // The IUnknown interface methods.
  virtual STDMETHODIMP QueryInterface(REFIID interface_id, void **object) {
    if (!object) {
      return E_INVALIDARG;
    }
    *object = nullptr;

    // 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 *>(
          static_cast<ITfCandidateListUIElement *>(this));
    } else if (IsEqualIID(interface_id, IID_ITfUIElement)) {
      *object = static_cast<ITfUIElement *>(
          static_cast<ITfCandidateListUIElement *>(this));
    } else if (IsEqualIID(interface_id, IID_ITfCandidateListUIElement)) {
      *object = static_cast<ITfCandidateListUIElement *>(this);
    } else if (IsEqualIID(interface_id,
                          IID_ITfCandidateListUIElementBehavior)) {
      *object = static_cast<ITfCandidateListUIElementBehavior *>(this);
    }

    if (*object == nullptr) {
      return E_NOINTERFACE;
    }

    AddRef();
    return S_OK;
  }

  virtual ULONG STDMETHODCALLTYPE AddRef() {
    return ref_count_.AddRefImpl();
  }

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

  void OnUpdate() {
    // 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 UpdateUiEditSession(
        text_service_, context_, this));

    HRESULT edit_session_result = S_OK;
    const HRESULT result = context_->RequestEditSession(
        text_service_->GetClientID(),
        edit_session,
        TF_ES_ASYNCDONTCARE | TF_ES_READ, &edit_session_result);
  }

  // Returns true when handled.
  bool HandleMouseEvent(
      UINT nFlags, const CPoint &point, bool select_candidate) {
    const Candidates candidates = output_.candidates();
    for (size_t i = 0; i < candidates.candidate_size(); ++i) {
      const Candidate &candidate = candidates.candidate(i);

      const CRect rect = ToCRect(table_layout_.GetRowRect(i));
      if (rect.PtInRect(point)) {
        if (select_candidate) {
          TipEditSession::SelectCandidateAsync(
              text_service_, context_, candidate.id());
          return true;
        } else {
          const int focused_array_index = GetFocusedArrayIndex(candidates);
          if (i != focused_array_index) {
            TipEditSession::HilightCandidateAsync(
                text_service_, context_, candidate.id());
            return true;
          }
          return false;
        }
      }
    }
    return false;
  }

  void ShowWindow(bool content_changed) {
    window_.ShowWindow(SW_SHOWNA);
    if (!window_visible_) {
      ::NotifyWinEvent(
          EVENT_OBJECT_IME_SHOW, window_.m_hWnd, OBJID_WINDOW, CHILDID_SELF);
    } else if (content_changed) {
      ::NotifyWinEvent(
          EVENT_OBJECT_IME_CHANGE, window_.m_hWnd, OBJID_WINDOW, CHILDID_SELF);
    }
    window_visible_ = true;
  }

  void HideWindow() {
    window_.ShowWindow(SW_HIDE);
    if (window_visible_) {
      ::NotifyWinEvent(
          EVENT_OBJECT_IME_HIDE, window_.m_hWnd, OBJID_WINDOW, CHILDID_SELF);
    }
    window_visible_ = false;
  }

  void Render(const RenderingInfo &info) {
    // Should be compared here before |output_| is synced to |info.output|.
    const bool content_changed =
        (target_rect_ != info.target_rect) ||
        (output_.SerializeAsString() != info.output.SerializeAsString());

    output_.CopyFrom(info.output);
    if (info.has_target_rect) {
      target_rect_ = info.target_rect;
      RenderImpl();
    }

    BOOL shown = FALSE;
    delegate_->IsShown(&shown);
    if (!shown) {
      HideWindow();
    } else {
      ShowWindow(content_changed);
    }
  }

  LRESULT WindowProc(
      HWND window_handle, UINT message, WPARAM wparam, LPARAM lparam) {
    switch (message) {
      case WM_MOZC_IMMERSIVE_WINDOW_UPDATE:
        OnUpdate();
        return 0;
      case WM_MOUSEACTIVATE:
        return MA_NOACTIVATE;
      case WM_LBUTTONDOWN:
        HandleMouseEvent(static_cast<UINT>(wparam),
                         CPoint(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)),
                         false);
        return ::DefWindowProcW(window_handle, message, wparam, lparam);
      case WM_LBUTTONUP:
        HandleMouseEvent(static_cast<UINT>(wparam),
                         CPoint(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)),
                         true);
        return ::DefWindowProcW(window_handle, message, wparam, lparam);
      case WM_MOUSEMOVE:
        if ((static_cast<UINT>(wparam) & MK_LBUTTON) == MK_LBUTTON) {
          HandleMouseEvent(static_cast<UINT>(wparam),
                           CPoint(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)),
                           false);
        }
        return ::DefWindowProcW(window_handle, message, wparam, lparam);
      case WM_SETCURSOR:
        ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
        return 0;
      default:
        return ::DefWindowProcW(window_handle, message, wparam, lparam);
    }
  }

 private:
  void RenderImpl() {
    if (!output_.has_candidates()) {
      return;
    }
    CSize size;
    int left_offset = 0;
    CBitmap bitmap(TipUiRendererImmersive::Render(
        output_.candidates(), text_renderer_.get(), &table_layout_,
        &size, &left_offset));
    const CPoint target_point(target_rect_.left, target_rect_.bottom);
    Rect new_position(target_point.x - left_offset,
                      target_point.y,
                      size.cx,
                      size.cy);
    {
      const Rect preedit_rect(target_rect_.left,
                              target_rect_.top,
                              target_rect_.Width(),
                              target_rect_.Height());
      const Size window_size(size.cx, size.cy);
      const Point zero_point_offset(left_offset, 0);
      Rect working_area;
      CRect area;
      if (working_area_->GetWorkingAreaFromPoint(target_point, &area)) {
        working_area = Rect(area.left, area.top, area.Width(), area.Height());
      }
      new_position =
          WindowUtil::GetWindowRectForMainWindowFromTargetPointAndPreedit(
              Point(target_point.x, target_point.y),
              preedit_rect,
              window_size,
              zero_point_offset,
              working_area,
              false);
    }
    CDC memdc;
    memdc.CreateCompatibleDC();
    const CBitmapHandle old_bitmap = memdc.SelectBitmap(bitmap);
    CPoint src_left_top(0, 0);
    CPoint new_top_left(new_position.Left(), new_position.Top());
    CSize new_size(new_position.Width(), new_position.Height());
    BLENDFUNCTION func = {AC_SRC_OVER, 0, 255, 0};
    ::UpdateLayeredWindow(window_.m_hWnd, nullptr, &new_top_left, &new_size,
                          memdc, &src_left_top, 0, &func, ULW_ALPHA);
    memdc.SelectBitmap(old_bitmap);
  }

  // This class is an implementation class for the ITfEditSession classes,
  // which is an observer for exclusively read the date from the text store.
  class UpdateUiEditSession : public ITfEditSession {
   public:
    // Destructor is kept as non-virtual because this class is designed to be
    // destroyed only by "delete this" in Release() method.
    // TODO(yukawa): put "final" keyword to the class declaration when C++11
    //     is allowed.
    ~UpdateUiEditSession();

    // The IUnknown interface methods.
    virtual STDMETHODIMP QueryInterface(REFIID interface_id, void **object);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    // The ITfEditSession interface method.
    // This function is called back by the TSF thread manager when an edit
    // request is granted.
    virtual HRESULT STDMETHODCALLTYPE DoEditSession(TfEditCookie read_cookie);
    UpdateUiEditSession(
        TipTextService *text_service, ITfContext *context,
        TipImmersiveUiElementImpl *ui_element);

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

    DISALLOW_COPY_AND_ASSIGN(UpdateUiEditSession);
  };

  // The ITfUIElement interface methods
  virtual HRESULT STDMETHODCALLTYPE GetDescription(BSTR *description) {
    return delegate_->GetDescription(description);
  }
  virtual HRESULT STDMETHODCALLTYPE GetGUID(GUID *guid) {
    return delegate_->GetGUID(guid);
  }
  virtual HRESULT STDMETHODCALLTYPE Show(BOOL show) {
    return delegate_->Show(show);
  }
  virtual HRESULT STDMETHODCALLTYPE IsShown(BOOL *show) {
    return delegate_->IsShown(show);
  }

  // The ITfCandidateListUIElement interface methods
  virtual HRESULT STDMETHODCALLTYPE GetUpdatedFlags(DWORD *flags) {
    return delegate_->GetUpdatedFlags(flags);
  }
  virtual HRESULT STDMETHODCALLTYPE GetDocumentMgr(
      ITfDocumentMgr **document_manager) {
    return delegate_->GetDocumentMgr(document_manager);
  }
  virtual HRESULT STDMETHODCALLTYPE GetCount(UINT *count) {
    return delegate_->GetCount(count);
  }
  virtual HRESULT STDMETHODCALLTYPE GetSelection(UINT *index) {
    return delegate_->GetSelection(index);
  }
  virtual HRESULT STDMETHODCALLTYPE GetString(UINT index, BSTR *text) {
    return delegate_->GetString(index, text);
  }
  virtual HRESULT STDMETHODCALLTYPE GetPageIndex(UINT *index, UINT size,
                                                 UINT *page_count) {
    return delegate_->GetPageIndex(index, size, page_count);
  }
  virtual HRESULT STDMETHODCALLTYPE SetPageIndex(UINT *index,
                                                 UINT page_count) {
    return delegate_->SetPageIndex(index, page_count);
  }
  virtual HRESULT STDMETHODCALLTYPE GetCurrentPage(UINT *current_page) {
    return delegate_->GetCurrentPage(current_page);
  }

  // The ITfCandidateListUIElementBehavior interface methods
  virtual HRESULT STDMETHODCALLTYPE SetSelection(UINT index) {
    return delegate_->SetSelection(index);
  }
  virtual HRESULT STDMETHODCALLTYPE Finalize() {
    return delegate_->Finalize();
  }
  virtual HRESULT STDMETHODCALLTYPE Abort() {
    return delegate_->Abort();
  }

  TipRefCount ref_count_;
  CComPtr<TipTextService> text_service_;
  CComPtr<ITfContext> context_;
  unique_ptr<TipUiElementDelegate> delegate_;
  unique_ptr<renderer::win32::WorkingAreaInterface> working_area_;
  unique_ptr<renderer::win32::TextRenderer> text_renderer_;
  CWindow window_;
  bool window_visible_;
  TableLayout table_layout_;
  CRect target_rect_;
  Output output_;
  DISALLOW_COPY_AND_ASSIGN(TipImmersiveUiElementImpl);
};

HWND GetOwnerWindow(ITfContext *context) {
  CComPtr<ITfContextView> context_view;
  if (FAILED(context->GetActiveView(&context_view)) || !context_view) {
    return nullptr;
  }

  HWND window_handle = nullptr;
  if (FAILED(context_view->GetWnd(&window_handle)) ||
      window_handle == nullptr) {
    window_handle = ::GetFocus();
  }
  return window_handle;
}

class WindowMap
    : public hash_map<HWND, TipImmersiveUiElementImpl *> {
};

class ThreadLocalInfo {
 public:
  ThreadLocalInfo() {}
  WindowMap *window_map() {
    return &window_map_;
  }

 private:
  WindowMap window_map_;

  DISALLOW_COPY_AND_ASSIGN(ThreadLocalInfo);
};

ThreadLocalInfo *GetThreadLocalInfo() {
  if (g_module_unloaded) {
    return nullptr;
  }
  if (g_tls_index == TLS_OUT_OF_INDEXES) {
    return nullptr;
  }
  ThreadLocalInfo *info = static_cast<ThreadLocalInfo *>(
      ::TlsGetValue(g_tls_index));
  if (info != nullptr) {
    // already initialized.
    return info;
  }
  info = new ThreadLocalInfo();
  ::TlsSetValue(g_tls_index, info);
  return info;
}

void EnsureThreadLocalInfoDestroyed() {
  if (g_module_unloaded) {
    return;
  }
  if (g_tls_index == TLS_OUT_OF_INDEXES) {
    return;
  }
  ThreadLocalInfo *info = static_cast<ThreadLocalInfo *>(
      ::TlsGetValue(g_tls_index));
  if (info == nullptr) {
    // already destroyed.
    return;
  }
  delete info;
  ::TlsSetValue(g_tls_index, nullptr);
}

LRESULT WINAPI WindowProc(HWND window_handle,
                          UINT message,
                          WPARAM wparam,
                          LPARAM lparam) {
  ThreadLocalInfo *info = GetThreadLocalInfo();
  if (info == nullptr) {
    return ::DefWindowProcW(window_handle, message, wparam, lparam);
  }

  const WindowMap::iterator it = info->window_map()->find(window_handle);
  if (it == info->window_map()->end()) {
    return ::DefWindowProcW(window_handle, message, wparam, lparam);
  }

  switch (message) {
    case WM_NCDESTROY: {
      const LRESULT result =
          it->second->WindowProc(window_handle, message, wparam, lparam);
      info->window_map()->erase(it);
      return result;
    }
    default:
      return it->second->WindowProc(window_handle, message, wparam, lparam);
  }
}

TipImmersiveUiElementImpl::UpdateUiEditSession::~UpdateUiEditSession() {}

    // The IUnknown interface methods.
STDMETHODIMP TipImmersiveUiElementImpl::UpdateUiEditSession::QueryInterface(
    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 *>(this);
  } else if (IsEqualIID(interface_id, IID_ITfEditSession)) {
    *object = static_cast<ITfEditSession *>(this);
  } else {
    *object = nullptr;
    return E_NOINTERFACE;
  }

  AddRef();
  return S_OK;
}

ULONG STDMETHODCALLTYPE
    TipImmersiveUiElementImpl::UpdateUiEditSession::AddRef() {
  return ref_count_.AddRefImpl();
}

ULONG STDMETHODCALLTYPE
    TipImmersiveUiElementImpl::UpdateUiEditSession::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.
HRESULT STDMETHODCALLTYPE
    TipImmersiveUiElementImpl::UpdateUiEditSession::DoEditSession(
    TfEditCookie read_cookie) {
  RenderingInfo info;
  if (FillRenderInfo(text_service_, context_, read_cookie, &info)) {
    ui_element_->Render(info);
  }
  return S_OK;
}

TipImmersiveUiElementImpl::UpdateUiEditSession::UpdateUiEditSession(
    TipTextService *text_service, ITfContext *context,
    TipImmersiveUiElementImpl *ui_element)
    : text_service_(text_service),
      context_(context),
      ui_element_(ui_element) {
}

}  // namespace

ITfUIElement *TipUiElementImmersive::New(
    TipTextService *text_service,
    ITfContext *context,
    HWND *window_handle) {
  if (window_handle == nullptr) {
    return nullptr;
  }
  *window_handle = nullptr;

  ThreadLocalInfo *info = GetThreadLocalInfo();
  if (info == nullptr) {
    return nullptr;
  }

  const HWND owner_window = GetOwnerWindow(context);
  if (!::IsWindow(owner_window)) {
    return nullptr;
  }
  const HWND window = ::CreateWindowExW(
      WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE,
      kImmersiveUIWindowClassName,
      L"",
      WS_POPUP,
      0, 0, 0, 0,
      owner_window,
      nullptr,
      g_module,
      nullptr);
  if (window == nullptr) {
    return nullptr;
  }
  TipImmersiveUiElementImpl *impl =
      new TipImmersiveUiElementImpl(text_service, context, window);
  (*info->window_map())[window] = impl;
  *window_handle = window;
  return static_cast<ITfCandidateListUIElement *>(impl);
}

void TipUiElementImmersive::OnActivate() {
  GetThreadLocalInfo();
}

void TipUiElementImmersive::OnDeactivate() {
  EnsureThreadLocalInfoDestroyed();
}

bool TipUiElementImmersive::OnDllProcessAttach(HINSTANCE module_handle,
                                               bool static_loading) {
  g_module = module_handle;
  g_tls_index = ::TlsAlloc();

  WNDCLASSEXW wc = {};
  wc.cbSize = sizeof(WNDCLASSEX);
  wc.style = CS_IME;
  wc.lpfnWndProc = WindowProc;
  wc.hInstance = module_handle;
  wc.lpszClassName = kImmersiveUIWindowClassName;

  const ATOM atom = ::RegisterClassExW(&wc);
  if (atom == INVALID_ATOM) {
    return false;
  }

  return true;
}

void TipUiElementImmersive::OnDllProcessDetach(HINSTANCE module_handle,
                                               bool process_shutdown) {
  if (g_tls_index != TLS_OUT_OF_INDEXES) {
    ::TlsFree(g_tls_index);
    g_tls_index = TLS_OUT_OF_INDEXES;
  }

  ::UnregisterClass(kImmersiveUIWindowClassName, module_handle);
  g_module_unloaded = true;
}

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