#include "nsIModule.h"
#include "nsIGenericFactory.h"
#include "nsCLABHash.h"
#include "nsCLABCMSMessage.h"
#include "nsCLABCMSDecoder.h"
#include "nsCLABCMSEncoder.h"
#include "nsCLABSignString.h"
#include "nsCLABScriptableInputStream.h"

#include "nsICategoryManager.h"
#include "nsIScriptNameSpaceManager.h"
#include "nsDOMCID.h"
#include "nsIDOMClassInfo.h"
#include "nsCRT.h"

#include "nsXPCOMGlue.h"

NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABHash)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABCMSMessage)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABCMSEncoder)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABCMSDecoder)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABSignString)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABScriptableInputStream)

NS_DECL_DOM_CLASSINFO(CLABSignString)

// 7f5275c6-30d2-4139-b921-74aedf70f33c
#define CLABEXTRAS_DOMCI_EXTENSION_CID   \
{ 0x7f5275c6, 0x30d2, 0x4139, {0xb9, 0x21, 0x74, 0xae, 0xdf, 0x70, 0xf3, 0x3c} }

#define CLABEXTRAS_DOMCI_EXTENSION_CONTRACTID \
"@mozilla.org/secclab/clabextras-domci-extender;1"

NS_DOMCI_EXTENSION(CLABExtras)
    static NS_DEFINE_CID(kCLABSignStringCID, NS_CLABSIGNSTRING_CID);
    NS_DOMCI_EXTENSION_ENTRY_BEGIN(CLABSignString)
        NS_DOMCI_EXTENSION_ENTRY_INTERFACE(nsICLABSignString)
    NS_DOMCI_EXTENSION_ENTRY_END_NO_PRIMARY_IF(CLABSignString, PR_TRUE, &kCLABSignStringCID)

NS_DOMCI_EXTENSION_END


class nsCLABExtrasNameset : public nsISupports
{
public:
  nsCLABExtrasNameset();
  virtual ~nsCLABExtrasNameset();

  // nsISupports
  NS_DECL_ISUPPORTS
};

nsCLABExtrasNameset::nsCLABExtrasNameset()
{
}

nsCLABExtrasNameset::~nsCLABExtrasNameset()
{
}

NS_INTERFACE_MAP_BEGIN(nsCLABExtrasNameset)
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

NS_IMPL_ADDREF(nsCLABExtrasNameset)
NS_IMPL_RELEASE(nsCLABExtrasNameset)

#define NS_CLAB_EXTRAS_CID                          \
 { /* cd6897a3-ce83-416f-bb86-4c56cc0add6d */      \
  0xcd6897a3, 0xce83, 0x416f,                      \
  {0xbb, 0x86, 0x4c, 0x56, 0xcc, 0x0a, 0xdd, 0x6d} }

#define NS_CLAB_EXTRAS_CONTRACTID "@mozilla.org/clabextras;1"

class nsCLABExtras : public nsISupports {
public:
  nsCLABExtras();
  virtual ~nsCLABExtras();

  NS_DEFINE_STATIC_CID_ACCESSOR(NS_CLAB_EXTRAS_CID);

  // nsISupports
  NS_DECL_ISUPPORTS
};

nsCLABExtras::nsCLABExtras()
{
}

nsCLABExtras::~nsCLABExtras()
{
}

NS_IMPL_ADDREF(nsCLABExtras)
NS_IMPL_RELEASE(nsCLABExtras)

NS_INTERFACE_MAP_BEGIN(nsCLABExtras)
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END


NS_GENERIC_FACTORY_CONSTRUCTOR(nsCLABExtras)

static NS_METHOD 
RegisterCLABExtras(nsIComponentManager *aCompMgr,
                  nsIFile *aPath,
                  const char *registryLocation,
                  const char *componentType,
                  const nsModuleComponentInfo *info)
{
  nsresult rv = NS_OK;
  int shutdown = 0;

  nsCOMPtr<nsIServiceManager> mgr;
  if (NS_GetServiceManager(getter_AddRefs(mgr)) == NS_ERROR_NOT_INITIALIZED){
    rv = XPCOMGlueStartup(nsnull);
    if (NS_SUCCEEDED(rv))
      shutdown = 1;
  }

  nsCOMPtr<nsICategoryManager> catman =
    do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);

  if (NS_FAILED(rv))
    goto FAIL;

  // nsXPIDLCString previous;
  rv = catman->AddCategoryEntry(JAVASCRIPT_DOM_CLASS,
                                "CLABSignString",
                                CLABEXTRAS_DOMCI_EXTENSION_CONTRACTID,
                                PR_TRUE, PR_TRUE,nsnull);// getter_Copies(previous));
  NS_ENSURE_SUCCESS(rv, rv);

 FAIL:
  if (shutdown){
    XPCOMGlueShutdown();
  }
  return rv;
}

static nsModuleComponentInfo components[] =
{
  {
    NS_CLABHASH_CLASSNAME, NS_CLABHASH_CID, NS_CLABHASH_CONTRACTID,nsCLABHashConstructor
  },
  {
    NS_CLABSCRIPTABLEINPUTSTREAM_CLASSNAME, NS_CLABSCRIPTABLEINPUTSTREAM_CID, NS_CLABSCRIPTABLEINPUTSTREAM_CONTRACTID,nsCLABScriptableInputStreamConstructor
  },
  {
    NS_CLABCMSMESSAGE_CLASSNAME, NS_CLABCMSMESSAGE_CID, NS_CLABCMSMESSAGE_CONTRACTID,nsCLABCMSMessageConstructor
  },
  {
    NS_CLABCMSDECODER_CLASSNAME, NS_CLABCMSDECODER_CID, NS_CLABCMSDECODER_CONTRACTID,nsCLABCMSDecoderConstructor
  },

  {
    NS_CLABCMSENCODER_CLASSNAME, NS_CLABCMSENCODER_CID, NS_CLABCMSENCODER_CONTRACTID,nsCLABCMSEncoderConstructor
  },

  {
    NS_CLABSIGNSTRING_CLASSNAME, NS_CLABSIGNSTRING_CID, NS_CLABSIGNSTRING_CONTRACTID,nsCLABSignStringConstructor,
  },

  {
    "CLABExtras component", NS_CLAB_EXTRAS_CID, NS_CLAB_EXTRAS_CONTRACTID,nsCLABExtrasConstructor,RegisterCLABExtras
  },
  { "CLAB Extras DOMCI Extender",
    CLABEXTRAS_DOMCI_EXTENSION_CID, CLABEXTRAS_DOMCI_EXTENSION_CONTRACTID,
    NS_DOMCI_EXTENSION_CONSTRUCTOR(CLABExtras) },

};

void PR_CALLBACK
CLABExtrasModuleDestructor(nsIModule* self)
{
  NS_IF_RELEASE(NS_CLASSINFO_NAME(CLABSignString));

}

NS_IMPL_NSGETMODULE_WITH_DTOR("SECCLAB", components, 
                              CLABExtrasModuleDestructor)
