// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/com_type_info_holder.h"

#include "base/lazy_instance.h"
#include "base/logging.h"

extern "C" IMAGE_DOS_HEADER __ImageBase;

namespace com_util {

base::LazyInstance<TypeInfoCache> type_info_cache(base::LINKER_INITIALIZED);

// TypeInfoCache

TypeInfoCache::~TypeInfoCache() {
  CacheMap::iterator it = cache_.begin();
  while (it != cache_.end()) {
    delete it->second;
    it++;
  }
}

TypeInfoNameCache* TypeInfoCache::Lookup(const IID* iid) {
  DCHECK(Singleton() == this);

  TypeInfoNameCache* tih = NULL;

  AutoLock lock(lock_);
  CacheMap::iterator it = cache_.find(iid);
  if (it == cache_.end()) {
    tih = new TypeInfoNameCache();
    HRESULT hr = tih ? tih->Initialize(*iid) : E_OUTOFMEMORY;
    if (SUCCEEDED(hr)) {
      cache_[iid] = tih;
    } else {
      NOTREACHED();
      delete tih;
      tih = NULL;
    }
  } else {
    tih = it->second;
  }

  return tih;
}

TypeInfoCache* TypeInfoCache::Singleton() {
  return type_info_cache.Pointer();
}

HRESULT TypeInfoNameCache::Initialize(const IID& iid) {
  DCHECK(type_info_ == NULL);

  wchar_t file_path[MAX_PATH];
  DWORD path_len = ::GetModuleFileNameW(reinterpret_cast<HMODULE>(&__ImageBase),
                                        file_path, arraysize(file_path));
  if (path_len == 0 || path_len == MAX_PATH) {
    NOTREACHED();
    return E_UNEXPECTED;
  }

  ScopedComPtr<ITypeLib> type_lib;
  HRESULT hr = LoadTypeLib(file_path, type_lib.Receive());
  if (SUCCEEDED(hr)) {
    hr = type_lib->GetTypeInfoOfGuid(iid, type_info_.Receive());
  }

  return hr;
}

// TypeInfoNameCache

HRESULT TypeInfoNameCache::GetIDsOfNames(OLECHAR** names, uint32 count,
                                         DISPID* dispids) {
  DCHECK(type_info_ != NULL);

  HRESULT hr = S_OK;
  for (uint32 i = 0; i < count && SUCCEEDED(hr); ++i) {
    NameToDispIdCache::HashType hash = NameToDispIdCache::Hash(names[i]);
    if (!cache_.Lookup(hash, &dispids[i])) {
      hr = type_info_->GetIDsOfNames(&names[i], 1, &dispids[i]);
      if (SUCCEEDED(hr)) {
        cache_.Add(hash, dispids[i]);
      }
    }
  }

  return hr;
}

HRESULT TypeInfoNameCache::Invoke(IDispatch* p, DISPID dispid, WORD flags,
                                  DISPPARAMS* params, VARIANT* result,
                                  EXCEPINFO* excepinfo, UINT* arg_err) {
  DCHECK(type_info_);
  HRESULT hr = type_info_->Invoke(p, dispid, flags, params, result, excepinfo,
                                  arg_err);
  DCHECK(hr != RPC_E_WRONG_THREAD);
  return hr;
}

// NameToDispIdCache

bool NameToDispIdCache::Lookup(HashType hash, DISPID* dispid) const {
  AutoLock lock(lock_);
  const DispidMap::const_iterator it = map_.find(hash);
  bool found = (it != map_.end());
  if (found)
    *dispid = it->second;
  return found;
}

void NameToDispIdCache::Add(HashType hash, DISPID dispid) {
  AutoLock lock(lock_);
  map_[hash] = dispid;
}

NameToDispIdCache::HashType NameToDispIdCache::Hash(const wchar_t* name) {
  return LHashValOfName(LANG_NEUTRAL, name);
}

}  // namespace com_util
