"use strict" ;

import ArrayMap from '../data/maps/ArrayMap'

import Task from '../process/Task'

import ObjectDefinition from './ObjectDefinition'

/**
 * Creates a container to register all the Object define by the corresponding {@link system.ioc.ObjectDefinition|ObjectDefinition} objects.
 * @name ObjectDefinitionContainer
 * @class
 * @memberof system.ioc
 * @extends system.process.Task
 */
class ObjectDefinitionContainer extends Task
{
    constructor()
    {
        super() ;
        Object.defineProperties( this ,
        {
            _map : { writable : true , value : new ArrayMap() }
        });
    }
    
    /**
     * Indicates the numbers of object definitions registered in the container.
     * @name numObjectDefinition
     * @memberof system.ioc.ObjectDefinitionContainer
     * @readonly
     * @instance
     */
    get numObjectDefinition () { return this._map.length ; }
    
    /**
     * Registers a new object definition in the container.
     * @param definition The Identifiable ObjectDefinition reference to register in the container.
     * @throws ArgumentError If the specified object definition is null or if this id attribut is null.
     * @name addObjectDefinition
     * @memberof system.ioc.ObjectDefinitionContainer
     * @function
     * @instance
     */
    addObjectDefinition( definition )
    {
        if ( definition instanceof ObjectDefinition )
        {
            this._map.set( definition.id , definition ) ;
        }
        else
        {
            throw new ReferenceError( this + " addObjectDefinition failed, the specified object definition must be an ObjectDefinition object." ) ;
        }
    }
    
    /**
     * Removes all the object definitions register in the container.
     * @name clearObjectDefinition
     * @memberof system.ioc.ObjectDefinitionContainer
     * @function
     * @instance
     */
    clearObjectDefinition()
    {
        this._map.clear() ;
    }
    
    /**
     * Returns a shallow copy of this object.
     * @return a shallow copy of this object.
     * @name clone
     * @memberof system.ioc.ObjectDefinitionContainer
     * @function
     * @instance
     */
    clone()
    {
        return new ObjectDefinitionContainer() ;
    }
    
    /**
     * Returns the ObjectDefinition object register in the container with the specified id.
     * @param {string} id - The id name of the ObjectDefinition to return.
     * @return the ObjectDefinition object register in the container with the specified id.
     * @throws ArgumentError If the specified object definition don't exist in the container.
     * @name getObjectDefinition
     * @memberof system.ioc.ObjectDefinitionContainer
     * @function
     * @instance
     */
    getObjectDefinition( id )
    {
        if ( this._map.has( id ) )
        {
            return this._map.get( id ) ;
        }
        else
        {
            throw new ReferenceError( this + " getObjectDefinition failed, the specified object definition don't exist : " + id ) ;
        }
    }
    
    /**
     * Returns <code>true</code> if the object defines with the specified id is register in the container.
     * @param {string} id - The id of the ObjectDefinition to search.
     * @return <code>true</code> if the object defines with the specified id is register in the container.
     * @name hasObjectDefinition
     * @memberof system.ioc.ObjectDefinitionContainer
     * @function
     * @instance
     */
    hasObjectDefinition( id )
    {
        return this._map.has( id ) ;
    }
    
    /**
     * Unregisters an object definition in the container.
     * @param id The id of the object definition to remove.
     * @throws ArgumentError If the specified object definition don't exist in the container.
     * @name removeObjectDefinition
     * @memberof system.ioc.ObjectDefinitionContainer
     * @function
     * @instance
     */
    removeObjectDefinition( id )
    {
        if ( this._map.has( id ) )
        {
            this._map.delete( id ) ;
        }
        else
        {
            throw new ReferenceError( this + " removeObjectDefinition failed, the specified object definition don't exist : " + id ) ;
        }
    }
}

export default ObjectDefinitionContainer;