STDMETHODIMP CPluginUserSettings::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispparams, VARIANT* pVarResult,
                                         EXCEPINFO* pExcepinfo, UINT* pArgErr)
{
  try
  {
    if (!pDispparams)
    {
      return E_POINTER;
    }
    if (pDispparams->cNamedArgs != 0)
    {
      return DISP_E_NONAMEDARGS;
    }
    CPluginSettings* settings = CPluginSettings::GetInstance();
    switch (dispidMember)
    {
    case dispatchID_GetMessage:
      {
        if (pDispparams->cArgs != 2)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_BSTR || pDispparams->rgvarg[1].vt != VT_BSTR)
        {
          return DISP_E_TYPEMISMATCH;
        }
        if (pVarResult)
        {
          CComBSTR key = pDispparams->rgvarg[0].bstrVal;
          CComBSTR section = pDispparams->rgvarg[1].bstrVal;
          Dictionary* dictionary = Dictionary::GetInstance();
          std::wstring message = dictionary->Lookup(
            ToUtf8String(ToWstring(section)),
            ToUtf8String(ToWstring(key))
          );

          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(message.c_str());
        }
      }
      break;
    case dispatchID_GetLanguageCount:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          auto languageList = settings->GetFilterLanguageTitleList();

          pVarResult->vt = VT_I4;
          pVarResult->lVal = static_cast<LONG>(languageList.size());
        }
      }
      break;
    case dispatchID_GetLanguageByIndex:
      {
        if (pDispparams->cArgs != 1)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_I4)
        {
          return DISP_E_TYPEMISMATCH;
        }
        if (pVarResult)
        {
          int index = pDispparams->rgvarg[0].lVal;

          auto languageTitleList = settings->GetFilterLanguageTitleList();

          if (index < 0  ||  index >= static_cast<int>(languageTitleList.size()))
            return DISP_E_BADINDEX;

          std::wstring language;

          int loopIndex = 0;
          for (auto it = languageTitleList.begin(); it != languageTitleList.end(); ++it)
          {
            if (loopIndex == index)
            {
              language = it->first;
              break;
            }
            ++loopIndex;
          }

          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(language.c_str());
        }
      }
      break;
    case dispatchID_GetLanguageTitleByIndex:
      {
        if (pDispparams->cArgs != 1)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_I4)
        {
          return DISP_E_TYPEMISMATCH;
        }
        if (pVarResult)
        {
          int index = pDispparams->rgvarg[0].lVal;

          auto languageTitleList = settings->GetFilterLanguageTitleList();

          if (index < 0  ||  index >= static_cast<int>(languageTitleList.size()))
            return DISP_E_BADINDEX;

          std::wstring languageTitle;
          int loopIndex = 0;
          for (auto it = languageTitleList.begin(); it != languageTitleList.end(); ++it)
          {
            if (loopIndex == index)
            {
              languageTitle = it->second;
              break;
            }
            loopIndex++;
          }

          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(languageTitle.c_str());
        }
      }
      break;
    case dispatchID_SetLanguage:
      {
        if (pDispparams->cArgs != 1)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_BSTR)
        {
          return DISP_E_TYPEMISMATCH;
        }
        CComBSTR url = pDispparams->rgvarg[0].bstrVal;
        settings->SetSubscription((BSTR)url);
      }
      break;
    case dispatchID_GetLanguage:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          std::wstring url = settings->GetSubscription();
          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(url.c_str());
        }
      }
      break;
    case dispatchID_GetWhitelistDomains:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          auto whiteListDomains = settings->GetWhiteListedDomainList();
          std::wstring commaSeparatedDomains;
          for (size_t i = 0; i < whiteListDomains.size(); i++)
          {
            if (!commaSeparatedDomains.empty())
            {
              commaSeparatedDomains += ',';
            }
            commaSeparatedDomains += whiteListDomains[i];
          }
          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(commaSeparatedDomains.c_str());
        }
      }
      break;
    case dispatchID_AddWhitelistDomain:
      {
        if (pDispparams->cArgs != 1)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_BSTR)
        {
          return DISP_E_TYPEMISMATCH;
        }
        CComBSTR domain = pDispparams->rgvarg[0].bstrVal;
        if (domain.Length())
        {
          settings->AddWhiteListedDomain((BSTR)domain);
        }
      }
      break;
    case dispatchID_RemoveWhitelistDomain:
      {
        if (pDispparams->cArgs != 1)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_BSTR)
        {
          return DISP_E_TYPEMISMATCH;
        }
        CComBSTR domain = pDispparams->rgvarg[0].bstrVal;
        if (domain.Length())
        {
          settings->RemoveWhiteListedDomain(std::wstring(domain));
        }
      }
      break;
    case dispatchID_GetAppLocale:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(GetBrowserLanguage().c_str());
        }
      }
      break;
    case dispatchID_GetDocumentationLink:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          pVarResult->vt = VT_BSTR;
          pVarResult->bstrVal = SysAllocString(CPluginClient::GetInstance()->GetDocumentationLink().c_str());
        }
      }
      break;
    case dispatchID_IsAcceptableAdsEnabled:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          pVarResult->vt = VT_BOOL;
          pVarResult->boolVal = CPluginClient::GetInstance()->IsAcceptableAdsEnabled() ? VARIANT_TRUE : VARIANT_FALSE;
        }
      }
      break;
    case dispatchID_SetAcceptableAdsEnabled:
      {
        if (pDispparams->cArgs != 1)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pDispparams->rgvarg[0].vt != VT_BOOL)
        {
          return DISP_E_TYPEMISMATCH;
        }
        if (pDispparams->rgvarg[0].boolVal != VARIANT_FALSE)
        {
          CPluginClient* client = CPluginClient::GetInstance();
          client->AddSubscription(client->GetPref(L"subscriptions_exceptionsurl", L""));
        }
        else
        {
          CPluginClient* client = CPluginClient::GetInstance();
          client->RemoveSubscription(client->GetPref(L"subscriptions_exceptionsurl", L""));
        }
      }
      break;
    case dispatchID_IsUpdate:
      {
        if (pDispparams->cArgs != 0)
        {
          return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult)
        {
          pVarResult->vt = VT_BOOL;
          pVarResult->boolVal = CPluginClient::GetInstance()->GetPref(L"displayUpdatePage", false) ? VARIANT_TRUE : VARIANT_FALSE;
        }
      }
      break;
    default:
      return DISP_E_MEMBERNOTFOUND;
      break;
    }
  }
  catch (...)
  {
    return E_FAIL;
  }
  return S_OK;
}
CString CPluginSettings::GetAppLocale()
{
  return ToCString(GetBrowserLanguage());
}