/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com)         |
   | Copyright (c) 1997-2010 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
*/

#include <runtime/ext/extension.h>
#include <runtime/base/complex_types.h>
#include <runtime/base/runtime_option.h>

using namespace std;

namespace HPHP {
///////////////////////////////////////////////////////////////////////////////

typedef std::map<std::string, Extension*, stdltistr> ExtensionMap;
static ExtensionMap *s_registered_extensions = NULL;
static bool s_modules_initialised = false;

// just to make valgrind cleaner
class ExtensionUninitializer {
public:
  ~ExtensionUninitializer() {
    delete s_registered_extensions;
  }
};
static ExtensionUninitializer s_extension_uninitializer;

///////////////////////////////////////////////////////////////////////////////

Extension::Extension(litstr name, const char *version /* = "" */)
    : m_name(name), m_version(version ? version : "") {
  if (s_registered_extensions == NULL) {
    s_registered_extensions = new ExtensionMap();
  }
  ASSERT(s_registered_extensions->find(name) ==
         s_registered_extensions->end());
  (*s_registered_extensions)[name] = this;
}

void Extension::LoadModules(Hdf hdf) {
  //  ASSERT(s_registered_extensions);
  if (s_registered_extensions == NULL) {
    s_registered_extensions = new ExtensionMap();
  }

  for (ExtensionMap::const_iterator iter = s_registered_extensions->begin();
       iter != s_registered_extensions->end(); ++iter) {
    iter->second->moduleLoad(hdf["Extensions"][iter->second->m_name]);
  }
}

void Extension::InitModules() {
  ASSERT(s_registered_extensions);
  for (ExtensionMap::const_iterator iter = s_registered_extensions->begin();
       iter != s_registered_extensions->end(); ++iter) {
    iter->second->moduleInit();
  }
  s_modules_initialised = true;
}

bool Extension::ModulesInitialised() {
  return s_modules_initialised;
}

void Extension::ShutdownModules() {
  ASSERT(s_registered_extensions);
  for (ExtensionMap::const_iterator iter = s_registered_extensions->begin();
       iter != s_registered_extensions->end(); ++iter) {
    iter->second->moduleShutdown();
  }
  s_registered_extensions->clear();
}

bool Extension::IsLoaded(CStrRef name) {
  if (name == "apc") {
    return RuntimeOption::EnableApc;
  }
  ASSERT(s_registered_extensions);
  return s_registered_extensions->find(name.data()) !=
    s_registered_extensions->end();
}

Extension *Extension::GetExtension(CStrRef name) {
  ASSERT(s_registered_extensions);
  ExtensionMap::iterator iter = s_registered_extensions->find(name.data());
  if (iter != s_registered_extensions->end()) {
    return iter->second;
  }
  return NULL;
}

Array Extension::GetLoadedExtensions() {
  ASSERT(s_registered_extensions);
  Array ret = Array::Create();
  for (ExtensionMap::const_iterator iter = s_registered_extensions->begin();
       iter != s_registered_extensions->end(); ++iter) {
    ret.append(iter->second->m_name);
  }
  return ret;
}

///////////////////////////////////////////////////////////////////////////////
}