// 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.

#include "chrome_frame/com_message_event.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"

ComMessageEvent::ComMessageEvent() {
}

ComMessageEvent::~ComMessageEvent() {
}

bool ComMessageEvent::Initialize(IOleContainer* container,
                                 const std::string& message,
                                 const std::string& origin,
                                 const std::string& event_type) {
  DLOG_IF(WARNING, !container) << __FUNCTION__ << " no container";
  message_ = message;
  origin_ = origin;
  type_ = event_type;

  // May remain NULL if container not IE
  base::win::ScopedComPtr<IHTMLEventObj> basic_event;
  base::win::ScopedComPtr<IHTMLDocument2> doc;

  // Fetching doc may fail in non-IE containers
  // and container might be NULL in some applications.
  if (container)
    container->QueryInterface(doc.Receive());
  if (doc) {
    base::win::ScopedComPtr<IHTMLDocument4> doc4;
    doc4.QueryFrom(doc);
    DCHECK(doc4);  // supported by IE5.5 and higher
    if (doc4) {
      // IHTMLEventObj5 is only supported in IE8 and later, so we provide our
      // own (minimalistic) implementation of it.
      doc4->createEventObject(NULL, basic_event.Receive());
      DCHECK(basic_event);
    }
  }

  basic_event_ = basic_event;
  return true;
}

STDMETHODIMP ComMessageEvent::GetTypeInfoCount(UINT* info) {
  // Don't DCHECK as python scripts might still call this function
  // inadvertently.
  DLOG(WARNING) << "Not implemented: " << __FUNCTION__;
  return E_NOTIMPL;
}

STDMETHODIMP ComMessageEvent::GetTypeInfo(UINT which_info, LCID lcid,
                                          ITypeInfo** type_info) {
  DLOG(WARNING) << "Not implemented: " << __FUNCTION__;
  return E_NOTIMPL;
}

STDMETHODIMP ComMessageEvent::GetIDsOfNames(REFIID iid, LPOLESTR* names,
                                            UINT count_names, LCID lcid,
                                            DISPID* dispids) {
  HRESULT hr = S_OK;

  // Note that since we're using LowerCaseEqualsASCII for string comparison,
  // the second argument _must_ be all lower case.  I.e. we cannot compare
  // against L"messagePort" since it has a capital 'P'.
  for (UINT i = 0; SUCCEEDED(hr) && i < count_names; ++i) {
    const wchar_t* name_begin = names[i];
    const wchar_t* name_end = name_begin + wcslen(name_begin);
    if (LowerCaseEqualsASCII(name_begin, name_end, "data")) {
      dispids[i] = DISPID_MESSAGE_EVENT_DATA;
    } else if (LowerCaseEqualsASCII(name_begin, name_end, "origin")) {
      dispids[i] = DISPID_MESSAGE_EVENT_ORIGIN;
    } else if (LowerCaseEqualsASCII(name_begin, name_end, "lasteventid")) {
      dispids[i] = DISPID_MESSAGE_EVENT_LAST_EVENT_ID;
    } else if (LowerCaseEqualsASCII(name_begin, name_end, "source")) {
      dispids[i] = DISPID_MESSAGE_EVENT_SOURCE;
    } else if (LowerCaseEqualsASCII(name_begin, name_end, "messageport")) {
      dispids[i] = DISPID_MESSAGE_EVENT_MESSAGE_PORT;
    } else if (LowerCaseEqualsASCII(name_begin, name_end, "type")) {
      dispids[i] = DISPID_MESSAGE_EVENT_TYPE;
    } else {
      if (basic_event_) {
        hr = basic_event_->GetIDsOfNames(IID_IDispatch, &names[i], 1, lcid,
                                         &dispids[i]);
      } else {
        hr = DISP_E_MEMBERNOTFOUND;
      }

      if (FAILED(hr)) {
        DLOG(WARNING) << "member not found: " << names[i]
                      << base::StringPrintf(L"0x%08X", hr);
      }
    }
  }
  return hr;
}

STDMETHODIMP ComMessageEvent::Invoke(DISPID dispid, REFIID iid, LCID lcid,
                                     WORD flags, DISPPARAMS* params,
                                     VARIANT* result, EXCEPINFO* excepinfo,
                                     UINT* arg_err) {
  HRESULT hr = DISP_E_MEMBERNOTFOUND;
  switch (dispid) {
    case DISPID_MESSAGE_EVENT_DATA:
      hr = GetStringProperty(flags, UTF8ToWide(message_).c_str(), result);
      break;

    case DISPID_MESSAGE_EVENT_ORIGIN:
      hr = GetStringProperty(flags, UTF8ToWide(origin_).c_str(), result);
      break;

    case DISPID_MESSAGE_EVENT_TYPE:
      hr = GetStringProperty(flags, UTF8ToWide(type_).c_str(), result);
      break;

    case DISPID_MESSAGE_EVENT_LAST_EVENT_ID:
      hr = GetStringProperty(flags, L"", result);
      break;

    case DISPID_MESSAGE_EVENT_SOURCE:
    case DISPID_MESSAGE_EVENT_MESSAGE_PORT:
      if (flags & DISPATCH_PROPERTYGET) {
        result->vt = VT_NULL;
        hr = S_OK;
      } else {
        hr = DISP_E_TYPEMISMATCH;
      }
      break;

    default:
      if (basic_event_) {
        hr = basic_event_->Invoke(dispid, iid, lcid, flags, params, result,
                                  excepinfo, arg_err);
      }
      break;
  }

  return hr;
}

HRESULT ComMessageEvent::GetStringProperty(WORD flags, const wchar_t* value,
                                           VARIANT* result) {
  if (!result)
    return E_INVALIDARG;

  HRESULT hr;
  if (flags & DISPATCH_PROPERTYGET) {
    result->vt = VT_BSTR;
    result->bstrVal = ::SysAllocString(value);
    hr = S_OK;
  } else {
    hr = DISP_E_TYPEMISMATCH;
  }
  return hr;
}
