/*****************************************************
*  
*  Copyright 2009 Adobe Systems Incorporated.  All Rights Reserved.
*  
*****************************************************
*  The contents of this file are subject to the Mozilla Public License
*  Version 1.1 (the "License"); you may not use this file except in
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*   
*  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.
*   
*  
*  The Initial Developer of the Original Code is Adobe Systems Incorporated.
*  Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems 
*  Incorporated. All Rights Reserved. 
*  
*****************************************************/
package org.osmf.elements
{
	import org.osmf.elements.compositeClasses.CompositeMetadata;
	import org.osmf.elements.compositeClasses.CompositionMode;
	import org.osmf.metadata.Metadata;
	import org.osmf.traits.MediaTraitBase;
	
	/**
	 * ParallelElement is a media composition whose elements are presented
	 * in parallel (concurrently).
	 * 
	 * <p>The media elements that make up a ParallelElement are treated as a
	 * single, unified media element.  For example, if a ParallelElement
	 * encapsulates a image and a piece of audio, the ParallelElement will
	 * behave as if it's a single MediaElement with the audio characteristics
	 * of the audio file and the display characteristics of the image file.</p>
	 * 
	 * <p>Typically, a trait on a ParallelElement is a composite or merged combination
	 * of that trait on all its children.  When a new media element is added as a child
	 * of the media composition,  either its traits or the composite's traits are adjusted
	 * to make the traits of the media composition and its children consistent.</p>
	 * <p> As an example of the first case, consider AudioTrait.
	 * If a client adds a new MediaElement that has its AudioTrait volume at 0.5
	 * to a ParallelElement that has its AudioTrait volume at 0.3,
	 * the AudioTrait volume for the child MediaElement is set to 0.3
	 * to be consistent with ParallelElement's trait.</p>
	 * <p>As an example of the second case, consider BufferTrait.
	 * If the added MediaElement has a BufferTrait, the ParallelElement's
	 * BufferTrait may need to "grow" if the new MediaElement has a
	 * larger buffer than any of its other children. In this case, the buffer of the 
	 * ParallelElement adjusts to the size of its new child.
	 * </p>
	 * 
	 * Here is how each trait is expressed when in parallel:
	 * <ul>
	 * <li>
	 * AudioTrait - The composite trait keeps the audible properties of all
	 * children in sync.  When the volume of a child element (or the composite
	 * element) is changed, the volume is similarly changed for all audible
	 * children (and for the composite trait).
	 * </li>
	 * <li>
	 * BufferTrait - The composite trait is buffering if any child is buffering.
	 * Its length and size are the length and size of the child with the
	 * longest buffer.  Its starting position is the minimum (earliest)
	 * starting position of all of its children.
	 * </li>
	 * <li>
	 * DisplayObjectTrait - If one or more of the composite’s children has the DisplayObjectTrait,
	 * the composite trait’s spatial dimensions are defined by the bounding box
	 * of the DisplayObject referenced by
	 * the <code>displayObject</code> property of the composite's DisplayObjectTrait.
	 * If none of the composite’s children has the DisplayObjectTrait,
	 * the composite trait's <code>mediaWidth</code> is the width of its widest child and its
	 * <code>mediaHeight</code> is the height of its tallest child.
	 * </li>
	 * <li>
	 * DRMTrait - The composite trait attempts to keep the DRM state of all children
	 * in sync.  When a child element is authenticated, all DRM-enabled children are
	 * simultaneously authenticated.
	 * </li>
	 * <li>
	 * DVRTrait - The composite trait attempts to keep the DVR state of all children
	 * in sync.
	 * </li>
	 * <li>
	 * DynamicStreamTrait - The composite trait attempts to keep the dynamic streaming
	 * state of all children in sync.  Specifically, it attempts to keep the
	 * <code>autoSwitch</code> property the same for all elements, and the current
	 * stream items within a similar bitrate range.
	 * </li>
	 * <li>
	 * LoadTrait - The composite trait keeps the load state of all children in
	 * sync.  When a child element (or the composite element) is loaded, all
	 * loadable children (and the composite element) are simultaneously loaded.
	 * </li>
	 * <li>
	 * PlayTrait - The composite trait keeps the pause and play states of all children in
	 * sync.  When a child element (or the composite element) is paused, all
	 * pausable children (and the composite element) are simultaneously paused. 
	 * When a child element (or the composite element) is played, all
	 * playable children (and the composite element) are simultaneously played.
	 * </li>
	 * <li>
	 * SeekTrait - The composite trait keeps the seek state of all children in
	 * sync.  When a child element (or the composite element) performs a seek,
	 * all seekable children (and the composite element) simultaneously perform
	 * that same seek. 
	 * </li>
	 * <li>
	 * TimeTrait - The composite trait represents a timeline that encapsulates
	 * the timelines of all children. Its duration is the maximum of the
	 * durations of all children.  Its position is kept in sync for all
	 * children, with the obvious caveat that a child's position will never be
	 * greater than its duration.
	 * </li>
	 * </ul>
	 * 
	 * 	@includeExample ParallelElementExample.as  -noswf
	 * 
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion OSMF 1.0
	 */
	public class ParallelElement extends CompositeElement
	{
		/**
		 * Constructor.
		 *  
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion OSMF 1.0
		 */
		public function ParallelElement()
		{
			super();
		}
		
		// Overrides
		//
		
		/**
		 * @private
		 */
		override protected function createMetadata():Metadata
		{
			var result:Metadata = super.createMetadata();
			CompositeMetadata(result).mode = CompositionMode.PARALLEL;
			
			return result;
		}
		
		/**
		 * @private
		 */			
		override protected function processAggregatedTrait(traitType:String, trait:MediaTraitBase):void
		{
			super.processAggregatedTrait(traitType, trait);
			
			var compositeTrait:MediaTraitBase = getTrait(traitType);

			// Create the composite trait if it doesn't exist yet.
			if (compositeTrait == null)
			{
				compositeTrait = traitFactory.createTrait
						( traitType
						, traitAggregator
						, CompositionMode.PARALLEL
						, this
						);

				if (compositeTrait != null)
				{
					addTrait(traitType, compositeTrait);
				}
			}
		}
		/**
		 * @private
		 */	
		override protected function processUnaggregatedTrait(traitType:String, trait:MediaTraitBase):void
		{
			super.processUnaggregatedTrait(traitType, trait);
			
			// Remove the composite trait if the unaggregated trait was the
			// last child of the composite trait.
			if (traitAggregator.hasTrait(traitType) == false)
			{
				removeTrait(traitType);
			}
		}
	}
}