// vim: ts=2 sw=2 expandtab cindent
//
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2008
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
//

function DEBUG (x) { debug ('flockSingleton: '+x+'\n'); }

const CLASS_ID = Components.ID ('{df938052-196a-429a-88b5-f72af6b56689}');
const CLASS_NAME = 'Flock JavaScript Singleton Service';
const CONTRACT_ID = '@flock.com/singleton;1';
const INTERFACES = [
  Components.interfaces.nsISupports,
  Components.interfaces.nsIClassInfo,
  Components.interfaces.flockISingleton
];

// ===================================================
// ========== BEGIN flockSingleton class ==========
// ===================================================

function flockSingleton ()
{
  this.mInstances = {};
  this.mLoader = Components.classes['@mozilla.org/moz/jssubscript-loader;1']
    .getService(Components.interfaces.mozIJSSubScriptLoader);
}

// BEGIN nsISupports interface
flockSingleton.prototype.QueryInterface =
function flockSingleton_QueryInterface (aIID)
{
  var interfaces = INTERFACES;
  for (var i in interfaces) {
    if (aIID.equals (interfaces[i])) {
      return this;
    }
  }
  throw Components.results.NS_ERROR_NO_INTERFACE;
}
// END nsISupports interface


// BEGIN nsIClassInfo interface
flockSingleton.prototype.contractID = CONTRACT_ID;
flockSingleton.prototype.classID = CLASS_ID;
flockSingleton.prototype.classDescription = CLASS_NAME;
flockSingleton.prototype.implementationLanguage = 
        Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT;
flockSingleton.prototype.flags = Components.interfaces.nsIClassInfo.SINGLETON;

flockSingleton.prototype.getInterfaces =
function flockSingleton_getInterfaces (aCount)
{
  var interfaces = INTERFACES;
  aCount.value = interfaces.length;
  return interfaces;
}

flockSingleton.prototype.getHelperForLanguage =
function flockSingleton_getHelperForLanguage (aLanguage)
{
  return null;
}
// END nsIClassInfo interface


// BEGIN flockISingleton interface
flockSingleton.prototype.getSingleton =
function flockSingleton_getSingleton (aURI)
{
    if (!this.mInstances[aURI]) {
        // we need to load the script
        var context = {};
        // load the script
        this.mLoader.loadSubScript (aURI, context);
        // see if we should use a specific object instead of the script context
        if (context.__singleton__) {
            this.mInstances[aURI] = context.__singleton__;
        } else {
            this.mInstances[aURI] = context;
        }
    }
    return { wrappedJSObject: this.mInstances[aURI] };
}
// END flockISingleton interface


// ========== END flockSingleton class ==========


// ========== BEGIN XPCOM Support ==========

var Module = {
  _firstTime: true,
  registerSelf: function (aCompMgr, aFileSpec, aLocation, aType)
  {
    if (this._firstTime) {
      this._firstTime = false;
      throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
    }
    aCompMgr = aCompMgr.QueryInterface (Components.interfaces.nsIComponentRegistrar);
    aCompMgr.registerFactoryLocation (CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
  },

  unregisterSelf: function (aCompMgr, aLocation, aType)
  {
    aCompMgr = aCompMgr.QueryInterface (Components.interfaces.nsIComponentRegistrar);
    aCompMgr.unregisterFactoryLocation (CLASS_ID, aLocation);        
  },
  
  getClassObject: function (aCompMgr, aCID, aIID)
  {
    if (!aIID.equals (Components.interfaces.nsIFactory)) {
      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
    }
    if (aCID.equals (CLASS_ID)) {
      return Factory;
    }
    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  canUnload: function (aCompMgr) { return true; }
};

var Factory = {
  createInstance: function (aOuter, aIID)
  {
    if (aOuter != null) {
      throw Components.results.NS_ERROR_NO_AGGREGATION;
    }
    return (new flockSingleton ()).QueryInterface (aIID);
  }
};

function NSGetModule (aCompMgr, aFileSpec)
{
  return Module;
}

// ========== END XPCOM Support ==========
