// Copyright (c) 2011 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.

#ifndef CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_
#define CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_

#include <map>
#include <ocidl.h>  // IProvideClassInfo2

#include "base/synchronization/lock.h"
#include "base/win/scoped_comptr.h"

#define NO_VTABLE __declspec(novtable)

namespace com_util {

// A map from a name hash (32 bit value) to a DISPID.
// Used as a caching layer before looking the name up in a type lib.
class NameToDispIdCache {
 public:
  typedef uint32 HashType;

  bool Lookup(HashType hash, DISPID* dispid) const;
  void Add(HashType hash, DISPID dispid);

  // Hashes the name by calling LHashValOfName.
  // The returned hash value is independent of the case of the characters
  // in |name|.
  static HashType Hash(const wchar_t* name);

 protected:
  typedef std::map<HashType, DISPID> DispidMap;
  DispidMap map_;
  mutable base::Lock lock_;
};

// Wraps an instance of ITypeInfo and builds+maintains a cache of names
// to dispids.  Also offers an Invoke method that simply forwards the call
// to ITypeInfo::Invoke.
class TypeInfoNameCache {
 public:
  // Loads the module's type library and fetches the ITypeInfo object for
  // the specified interface ID.
  HRESULT Initialize(const IID& iid);

  // Fetches the id's of the given names.  If there's a cache miss, the results
  // are fetched from the underlying ITypeInfo and then cached.
  HRESULT GetIDsOfNames(OLECHAR** names, uint32 count, DISPID* dispids);

  // Calls ITypeInfo::Invoke.
  HRESULT Invoke(IDispatch* p, DISPID dispid, WORD flags, DISPPARAMS* params,
                 VARIANT* result, EXCEPINFO* excepinfo, UINT* arg_err);

  inline ITypeInfo* CopyTypeInfo() {
    ITypeInfo* ti = type_info_.get();
    if (ti)
      ti->AddRef();
    return ti;
  }

 protected:
  base::win::ScopedComPtr<ITypeInfo> type_info_;
  NameToDispIdCache cache_;
};

// The root class for type lib access.
// This class has only one instance that should be accessed via the
// Singleton method.
class TypeInfoCache {
 public:
  TypeInfoCache() {
  }

  ~TypeInfoCache();

  // Looks up a previously cached TypeInfoNameCache instance or creates and
  // caches a new one.
  TypeInfoNameCache* Lookup(const IID* iid);

  // Call to get access to the singleton instance of TypeInfoCache.
  static TypeInfoCache* Singleton();

 protected:
  typedef std::map<const IID*, TypeInfoNameCache*> CacheMap;
  base::Lock lock_;
  CacheMap cache_;
};

// Holds a pointer to the type info of a given COM interface.
// The type info is loaded once on demand and after that cached.
// NOTE: This class only supports loading the first typelib from the
// current module.
template <const IID& iid>
class TypeInfoHolder {
 public:
  TypeInfoHolder() : type_info_(NULL) {
  }

  bool EnsureTI() {
    if (!type_info_)
      type_info_ = TypeInfoCache::Singleton()->Lookup(&iid);
    return type_info_ != NULL;
  }

  HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** info) {
    if (EnsureTI()) {
      *info = type_info_->CopyTypeInfo();
      return S_OK;
    }

    return E_UNEXPECTED;
  }

  HRESULT GetIDsOfNames(REFIID riid, OLECHAR** names, UINT count, LCID lcid,
                        DISPID* dispids) {
    if (!EnsureTI())
      return E_UNEXPECTED;
    return type_info_->GetIDsOfNames(names, count, dispids);
  }

  HRESULT Invoke(IDispatch* p, DISPID dispid, REFIID riid, LCID lcid,
                 WORD flags, DISPPARAMS* params, VARIANT* result,
                 EXCEPINFO* excepinfo, UINT* arg_err) {
    if (!EnsureTI())
      return E_UNEXPECTED;

    return type_info_->Invoke(p, dispid, flags, params, result, excepinfo,
                              arg_err);
  }

 protected:
  TypeInfoNameCache* type_info_;
};

// Implements IDispatch part of T (where T is an IDispatch derived interface).
// The class assumes that the type info of T is available in a typelib of the
// current module.
template <class T, const IID& iid = __uuidof(T)>
class NO_VTABLE IDispatchImpl : public T {
 public:
  STDMETHOD(GetTypeInfoCount)(UINT* count) {
    if (count == NULL)
      return E_POINTER;
    *count = 1;
    return S_OK;
  }

  STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) {
    return type_info_.GetTypeInfo(itinfo, lcid, pptinfo);
  }

  STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* names, UINT count,
                           LCID lcid, DISPID* dispids) {
    return type_info_.GetIDsOfNames(riid, names, count, lcid, dispids);
  }
  STDMETHOD(Invoke)(DISPID dispid, REFIID riid, LCID lcid, WORD flags,
                    DISPPARAMS* params, VARIANT* result, EXCEPINFO* excepinfo,
                    UINT* arg_err) {
    return type_info_.Invoke(static_cast<IDispatch*>(this), dispid, riid, lcid,
                             flags, params, result, excepinfo, arg_err);
  }

 protected:
  TypeInfoHolder<iid> type_info_;
};

// Simple implementation of IProvideClassInfo[2].
template <const CLSID& class_id, const IID& source_iid>
class NO_VTABLE IProvideClassInfo2Impl : public IProvideClassInfo2 {
 public:
  STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) {
    return type_info_.GetTypeInfo(0, LANG_NEUTRAL, pptinfo);
  }

  STDMETHOD(GetGUID)(DWORD guid_kind, GUID* guid) {
    if (guid == NULL || guid_kind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
      return E_INVALIDARG;

    *guid = source_iid;

    return S_OK;
  }

 protected:
  TypeInfoHolder<class_id> type_info_;
};

}  // namespace com_util

#endif  // CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_
