/**
 * INativeControls: load
 */
STDMETHODIMP CNativeControls::load(BSTR _uuid, BSTR _extensionPath, unsigned int instanceId, ULONG hwnd)
{
  HRESULT hr = E_FAIL;

  wstring uuid = _uuid;
  bfs::wpath extensionPath = bfs::wpath(_extensionPath);
  m_frame = (HWND)hwnd;

  HWND target = nullptr;

  logger->debug(L"CNativeControls::load"
    L" -> " + uuid +
    L" -> " + extensionPath.wstring() +
    L" -> " + boost::lexical_cast<wstring>(instanceId)+
    L" -> " + boost::lexical_cast<wstring>(m_frame));

  for (;;) {
    // load manifest
    auto scriptExtensions = ScriptExtensions::pointer(new ScriptExtensions(extensionPath));
    BreakOnNull(scriptExtensions, hr);
    if (!scriptExtensions->manifest) {
      logger->error(L"Failed to read manifest file: " + scriptExtensions->pathManifest.wstring() + L" at: " + extensionPath.wstring());
      break;
    }

    m_extensionPaths[uuid] = extensionPath;
    m_extensionManifests[uuid] = scriptExtensions->manifest;

    // get toolbar HWND from IEFrame HWND
    HWND toolbar = WindowsMessage::GetToolbar(m_frame, &toolbar, &target);
    if (!toolbar || !target) {
      logger->error(L"CNativeControls::load failed to get ToolbarWindow32");
      break;
    }

    // inject proxy lib into frame process
    m_frameProxy = new FrameProxy(L"NativeControls", _AtlModule.moduleHandle, toolbar, target);
    BreakOnNull(m_frameProxy, hr);

    // create popup
    PopupWindow::pointer popup = m_popupWindows[uuid];
    if (!popup) {
      logger->debug(L"CNativeControls::load creating popup -> " + wstring(uuid));

      // get default url for popup 
      Manifest::pointer manifest = m_extensionManifests[uuid];
      if (!manifest) {
        logger->error(L"CNativeControls::load no manifest for extension -> " + wstring(uuid));
        break;
      }

      bfs::wpath path = m_extensionPaths[uuid] / manifest->browser_action.default_popup;
      wstring url = L"file://" + path.wstring();

      // get a popup parent that doesn't competely tie IE's knickers into a knot
      HWND parent = m_frame;
      parent = ::FindWindowEx(parent, NULL, L"Frame Tab", NULL);
      if (!parent) {
        // In IE7 there is no intermediate "Frame Tab" window. If we didn't find
        // one try getting TabWindowClass directly from under m_frame.
        parent = m_frame;
      }

      parent = ::FindWindowEx(parent, NULL, L"TabWindowClass", NULL);
      if (!parent) {
        logger->error(L"CNativeControls::load failed: TabWindowClass");
        break;
      }

      POINT point = {0, 0};
      popup = PopupWindow::pointer(new PopupWindow(uuid, point, url));
      HWND hwnd = popup->Create(parent, CRect(point.x, point.y, point.x + PopupWindow::DEFAULT_WIDTH, point.y + PopupWindow::DEFAULT_HEIGHT), CComBSTR((L"Forge Popup " + wstring(uuid)).c_str()));
      if (!hwnd) {
        logger->error(L"CNativeControls::load failed to create popup");
        break;
      }
      m_popupWindows[uuid] = popup;
    }

    hr = S_OK; // if we are here - all went ok
    break;
  }

  return hr;
}
/**
 * INativeControls: load
 */
STDMETHODIMP CNativeControls::load(BSTR _uuid, BSTR _extensionPath, unsigned int instanceId, ULONG hwnd)
{
    wstring uuid             = _uuid;
    bfs::wpath extensionPath = bfs::wpath(_extensionPath);
    this->m_frame            = (HWND)hwnd;

    logger->debug(L"CNativeControls::load"
                  L" -> " + uuid +
                  L" -> " + extensionPath.wstring() +
                  L" -> " + boost::lexical_cast<wstring>(instanceId) +
                  L" -> " + boost::lexical_cast<wstring>(m_frame));

    // load manifest
    ScriptExtensions::pointer scriptExtensions =
        ScriptExtensions::pointer(new ScriptExtensions(extensionPath));
    if (!scriptExtensions->manifest) {
        logger->error(L"Failed to read manifest file: " +
                      scriptExtensions->pathManifest.wstring() + 
                      L" at: " + extensionPath.wstring());
        ::MessageBox(NULL,
                     wstring(L"Failed to read manifest. Please check that "
                             L" manifest.json file is present at " +
                             extensionPath.wstring() +
                             L" and properly configured.").c_str(),
                     L"trigger.io",
                     MB_TASKMODAL | MB_ICONEXCLAMATION);
        // TODO halt init and exit gracefully
        return E_FAIL;
    }
    m_extensionPaths[uuid] = extensionPath;
    m_extensionManifests[uuid] = scriptExtensions->manifest;

    // get toolbar HWND from IEFrame HWND
    HWND toolbar, target;
    toolbar = WindowsMessage::GetToolbar(m_frame, &toolbar, &target);
    if (!toolbar || !target) {
            logger->error(L"CNativeControls::load failed to get ToolbarWindow32");
            return E_FAIL;
    }

    // inject proxy lib into frame process
    m_frameProxy = new FrameProxy(L"NativeControls",
                                  _AtlModule.moduleHandle,
                                  toolbar, target);

    // create popup
    PopupWindow::pointer popup = m_popupWindows[uuid];
    if (!popup) { 
        logger->debug(L"CNativeControls::load creating popup"
                      L" -> " + wstring(uuid));

        // get default url for popup 
        Manifest::pointer manifest = m_extensionManifests[uuid];
        if (!manifest) {
            logger->error(L"CNativeControls::load "
                          L"no manifest for extension"
                          L" -> " + wstring(uuid));
            return E_FAIL;
        }
        bfs::wpath path = m_extensionPaths[uuid] / manifest->browser_action.default_popup;
        wstring url = L"file://" + path.wstring();

        // get a popup parent that doesn't competely tie IE's knickers into a knot
        HWND parent = m_frame;
        parent = ::FindWindowEx(parent, NULL, L"Frame Tab", NULL);
        if (!parent) {
            // In IE7 there is no intermediate "Frame Tab" window. If we didn't find
            // one try getting TabWindowClass directly from under m_frame.
            parent = m_frame;
        }
        parent = ::FindWindowEx(parent, NULL, L"TabWindowClass", NULL);
        if (!parent) { logger->error(L"CNativeControls::load failed: TabWindowClass"); return E_FAIL; }
        /*parent = ::FindWindowEx(parent, NULL, L"Shell DocObject View", NULL);
        if (!parent) { logger->error(L"CNativeControls::load failed: Shell DocObject View"); return E_FAIL; }
        parent = ::FindWindowEx(parent, NULL, L"Internet Explorer_Server", NULL);
        if (!parent) { logger->error(L"CNativeControls::load failed: Internet Explorer_Server"); return E_FAIL; }*/
        
        POINT point; point.x = 0; point.y = 0; 
        popup = PopupWindow::pointer(new PopupWindow(uuid, point, url));
        HWND hwnd;
        hwnd = popup->Create(parent,
                             CRect(point.x,
                                   point.y, 
                                   point.x + PopupWindow::DEFAULT_WIDTH,
                                   point.y + PopupWindow::DEFAULT_HEIGHT),
                             CComBSTR((L"Forge Popup " + wstring(uuid)).c_str()));
        if (!hwnd) {
            logger->error(L"CNativeControls::load "
                          L"failed to create popup");
            return E_FAIL;
        }
        m_popupWindows[uuid] = popup;
    }

    return S_OK;
}