// Copyright 2010-2014, 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/base/focus_hierarchy_observer.h"

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

#include <memory>

#include "base/logging.h"
#include "base/port.h"
#include "base/util.h"
#include "win32/base/accessible_object.h"
#include "win32/base/browser_info.h"

namespace mozc {
namespace win32 {
namespace {

using ::ATL::CComBSTR;
using ::ATL::CComPtr;
using ::ATL::CComQIPtr;
using ::ATL::CComVariant;

using ::std::unique_ptr;

const size_t kMaxHierarchyLevel = 50;

DWORD g_tls_index = TLS_OUT_OF_INDEXES;
HMODULE g_module_handle = nullptr;

string UTF16ToUTF8(const wstring &str) {
  string utf8;
  Util::WideToUTF8(str, &utf8);
  return utf8;
}

string GetWindowTestAsUTF8(HWND window_handle) {
  const int text_len = ::GetWindowTextLengthW(window_handle);
  if (text_len <= 0) {
    return "";
  }
  const int buffer_len = text_len + 1;
  unique_ptr<wchar_t[]> buffer(new wchar_t[buffer_len]);
  const int copied_len_without_null =
      ::GetWindowText(window_handle, buffer.get(), buffer_len);
  if (copied_len_without_null <= 0 ||
      copied_len_without_null + 1 > buffer_len) {
    return "";
  }
  return UTF16ToUTF8(wstring(buffer.get(), copied_len_without_null));
}

string GetWindowClassNameAsUTF8(HWND window_handle) {
  const int kBufferLen = 256 + 1;
  unique_ptr<wchar_t[]> buffer(new wchar_t[kBufferLen]);
  const int copied_len_without_null =
      ::GetClassNameW(window_handle, buffer.get(), kBufferLen);
  if (copied_len_without_null <= 0 ||
      copied_len_without_null + 1 > kBufferLen) {
    return "";
  }
  return UTF16ToUTF8(wstring(buffer.get(), copied_len_without_null));
}

DWORD GetProcessIdFromWindow(HWND window_handle) {
  DWORD process_id = 0;
  if (::GetWindowThreadProcessId(window_handle, &process_id) == 0) {
    return 0;
  }
  return process_id;
}

void FillWindowInfo(
    HWND window_handle,
    vector<FocusHierarchyObserver::WindowInfo> *window_hierarchy) {
  if (window_handle == nullptr) {
    // error
    window_hierarchy->clear();
    return;
  }
  const HWND ancestor = ::GetAncestor(window_handle, GA_ROOT);
  if (ancestor == nullptr) {
    // error
    window_hierarchy->clear();
    return;
  }
  while (true) {
    if (window_hierarchy->size() > kMaxHierarchyLevel) {
      window_hierarchy->clear();
      return;
    }
    FocusHierarchyObserver::WindowInfo element;
    element.window_handle = window_handle;
    element.title = GetWindowTestAsUTF8(window_handle);
    element.class_name = GetWindowClassNameAsUTF8(window_handle);
    element.process_id = GetProcessIdFromWindow(window_handle);
    window_hierarchy->push_back(element);
    if (window_handle == ancestor) {
      return;
    }
    window_handle = ::GetParent(window_handle);
    if (window_handle == nullptr) {
      return;
    }
  }
  DCHECK(false) << "must not reach here.";
}

void FillAccessibleInfo(
    AccessibleObject accessible,
    HWND focused_window_handle,
    vector<AccessibleObjectInfo> *hierarchy) {
  if (!accessible.IsValid()) {
    return;
  }

  hierarchy->push_back(accessible.GetInfo());

  while (true) {
    if (hierarchy->size() > kMaxHierarchyLevel) {
      hierarchy->clear();
      break;
    }
    AccessibleObject parent = accessible.GetParent();
    if (!parent.IsValid()) {
      break;
    }
    HWND parent_window_handle = nullptr;
    if (!parent.GetWindowHandle(&parent_window_handle) ||
        focused_window_handle != parent_window_handle) {
      // finish!
      break;
    }
    hierarchy->push_back(parent.GetInfo());
    accessible = parent;
  }
}

class ThreadLocalInfo {
 public:
  vector<AccessibleObjectInfo> ui_hierarchy() const {
    return ui_hierarchy_;
  }
  vector<FocusHierarchyObserver::WindowInfo> window_hierarchy() const {
    return window_hierarchy_;
  }
  string root_window_name() const {
    return root_window_name_;
  }

  void SyncFocusHierarchy() {
    const HWND focused_window = ::GetFocus();
    if (GetProcessIdFromWindow(focused_window) != ::GetCurrentProcessId()) {
      return;
    }

    AccessibleObject accesible = AccessibleObject::FromWindow(focused_window);
    if (accesible.IsValid()) {
      AccessibleObject focused_accesible = accesible.GetFocus();
      if (focused_accesible.IsValid()) {
        accesible = focused_accesible;
      }
    }
    OnInitialize(focused_window, accesible);
  }

  void AddRef() {
    ++ref_count_;
  }

  void Release() {
    --ref_count_;
    if (ref_count_ <= 0) {
      delete this;
    }
  }

  static ThreadLocalInfo *Self() {
    if (g_tls_index == TLS_OUT_OF_INDEXES) {
      return nullptr;
    }
    return static_cast<ThreadLocalInfo *>(::TlsGetValue(g_tls_index));
  }

  static ThreadLocalInfo *EnsureExists() {
    DCHECK_NE(TLS_OUT_OF_INDEXES, g_tls_index);
    auto *info = static_cast<ThreadLocalInfo *>(::TlsGetValue(g_tls_index));
    if (info == nullptr) {
      info = ThreadLocalInfo::Create();
    }
    return info;
  }

 private:
  explicit ThreadLocalInfo(HWINEVENTHOOK hook_handle)
      : ref_count_(0),
        hook_handle_(hook_handle) {
    ::TlsSetValue(g_tls_index, this);
  }

  ~ThreadLocalInfo() {
    if (hook_handle_ != nullptr) {
      ::UnhookWinEvent(hook_handle_);
      hook_handle_ = nullptr;
    }
    ::TlsSetValue(g_tls_index, nullptr);
  }

  static ThreadLocalInfo *Create() {
    if (g_module_handle == nullptr) {
      return nullptr;
    }

    auto hook_handle = ::SetWinEventHook(
        EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, g_module_handle,
        WinEventProc, ::GetCurrentProcessId(), ::GetCurrentThreadId(),
        WINEVENT_INCONTEXT);

    if (hook_handle == nullptr) {
      return nullptr;
    }

    return new ThreadLocalInfo(hook_handle);
  }

  static void CALLBACK WinEventProc(HWINEVENTHOOK hook_handle,
                                    DWORD event,
                                    HWND window_handle,
                                    LONG object_id,
                                    LONG child_id,
                                    DWORD event_thread,
                                    DWORD event_time) {
    if (g_module_handle == nullptr) {
      return;
    }

    if (!::IsWindow(window_handle)) {
      return;
    }

    if (event != EVENT_OBJECT_FOCUS) {
      return;
    }

    const DWORD window_process_id = GetProcessIdFromWindow(window_handle);
    if (window_process_id != ::GetCurrentProcessId()) {
      // avoid interprocess call.
      return;
    }

    auto *self = Self();
    if (self == nullptr) {
      return;
    }

    AccessibleObject accessible;
    {
      CComPtr<IAccessible> container;
      CComVariant child;
      HRESULT result = ::AccessibleObjectFromEvent(
          window_handle, object_id, child_id, &container, &child);
      if (SUCCEEDED(result) && (container != nullptr) && (child.vt == VT_I4)) {
        accessible = AccessibleObject(container, child.lVal);
      }
    }

    self->OnInitialize(window_handle, accessible);
  }

  void OnInitialize(HWND window_handle, AccessibleObject accessible) {
    ui_hierarchy_.clear();
    window_hierarchy_.clear();
    root_window_name_.clear();

    FillWindowInfo(window_handle, &window_hierarchy_);
    FillAccessibleInfo(accessible, window_handle, &ui_hierarchy_);

    if (!window_hierarchy_.empty()) {
      const HWND root_window_handle = window_hierarchy_.back().window_handle;
      const DWORD root_window_process_id =
          GetProcessIdFromWindow(root_window_handle);
      if (root_window_process_id != ::GetCurrentProcessId()) {
        // avoid interprocess call
        root_window_name_ = GetWindowTestAsUTF8(root_window_handle);
      } else {
        const AccessibleObject root_object =
            AccessibleObject::FromWindow(root_window_handle);
        if (root_object.IsValid()) {
          root_window_name_ = root_object.GetInfo().name;
        } else {
          root_window_name_ = GetWindowTestAsUTF8(root_window_handle);
        }
      }
    }
  }

  int ref_count_;
  HWINEVENTHOOK hook_handle_;
  vector<AccessibleObjectInfo> ui_hierarchy_;
  vector<FocusHierarchyObserver::WindowInfo> window_hierarchy_;
  string root_window_name_;
};

bool TlsAvailable() {
  return g_tls_index != TLS_OUT_OF_INDEXES;
}

class FocusHierarchyObserverImpl : public FocusHierarchyObserver {
 public:
  static FocusHierarchyObserver *Create() {
    if (!TlsAvailable()) {
      return nullptr;
    }
    auto *info = ThreadLocalInfo::EnsureExists();
    info->AddRef();
    return new FocusHierarchyObserverImpl();
  }

 private:
  FocusHierarchyObserverImpl() {
  }

  virtual ~FocusHierarchyObserverImpl() {
    auto *self = ThreadLocalInfo::Self();
    if (self != nullptr) {
      self->Release();
    }
  }

  // FocusHierarchyObserver overrides:
  virtual void SyncFocusHierarchy() {
    auto *self = ThreadLocalInfo::Self();
    if (self == nullptr) {
      return;
    }
    self->SyncFocusHierarchy();
  }
  virtual bool IsAbailable() const {
    return ThreadLocalInfo::Self() != nullptr;
  }
  virtual vector<AccessibleObjectInfo> GetUIHierarchy() const {
    auto *self = ThreadLocalInfo::Self();
    if (self == nullptr) {
      return vector<AccessibleObjectInfo>();
    }
    return self->ui_hierarchy();
  }
  virtual vector<WindowInfo> GetWindowHierarchy() const {
    auto *self = ThreadLocalInfo::Self();
    if (self == nullptr) {
      return vector<FocusHierarchyObserver::WindowInfo>();
    }
    return self->window_hierarchy();
  }
  virtual string GetRootWindowName() const {
    auto *self = ThreadLocalInfo::Self();
    if (self == nullptr) {
      return "";
    }
    return self->root_window_name();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(FocusHierarchyObserverImpl);
};

class FocusHierarchyObserverNullImpl : public FocusHierarchyObserver {
 public:
  FocusHierarchyObserverNullImpl() {
  }
  virtual ~FocusHierarchyObserverNullImpl() {
  }

 private:
  // FocusHierarchyObserver overrides:
  virtual void SyncFocusHierarchy() {
  }
  virtual bool IsAbailable() const {
    return false;
  }
  virtual vector<AccessibleObjectInfo> GetUIHierarchy() const {
    return vector<AccessibleObjectInfo>();
  }
  virtual vector<WindowInfo> GetWindowHierarchy() const {
    return vector<WindowInfo>();
  }
  virtual string GetRootWindowName() const {
    return "";
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(FocusHierarchyObserverNullImpl);
};

}   // namespace

FocusHierarchyObserver::~FocusHierarchyObserver() {
}

FocusHierarchyObserver::WindowInfo::WindowInfo()
    : window_handle(nullptr),
      process_id(0) {
}

// static
void FocusHierarchyObserver::OnDllProcessAttach(HINSTANCE module_handle,
                                                bool static_loading) {
  g_tls_index = ::TlsAlloc();
  g_module_handle = module_handle;
}

// static
void FocusHierarchyObserver::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;
  }
  g_module_handle = nullptr;
}

// static
FocusHierarchyObserver *FocusHierarchyObserver::Create() {
  // Note: Currently FocusHierarchyObserver is enabled only with Chromium.
  // TODO(yukawa): Extend the target applications.
  if (BrowserInfo::GetBrowerType() != BrowserInfo::kBrowserTypeChrome) {
    return new FocusHierarchyObserverNullImpl();
  }

  auto *impl = FocusHierarchyObserverImpl::Create();
  if (impl != nullptr) {
    return impl;
  }
  return new FocusHierarchyObserverNullImpl();
}

}  // namespace win32
}  // namespace mozc
