////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (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.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.effects
{

import mx.core.mx_internal;
import mx.effects.effectClasses.PropertyChanges;
import mx.effects.effectClasses.RemoveChildActionInstance;

use namespace mx_internal;

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="duration", kind="property")]

[Alternative(replacement="spark.effects.RemoveAction", since="4.0")]

/**
 *  The RemoveChildAction class defines an action effect that corresponds
 *  to the RemoveChild property of a view state definition.
 *  You use a RemoveChildAction effect within a transition definition
 *  to control when the view state change defined by a RemoveChild property
 *  occurs during the transition.
 *  
 *  @mxml
 *
 *  <p>The <code>&lt;mx:RemoveChildAction&gt;</code> tag
 *  inherits all of the tag attributes of its superclass,
 *  and adds the following tag attributes:</p>

 *  <pre>
 *  &lt;mx:RemoveChildAction
 *    <b>Properties</b>
 *    id="ID"
 *  /&gt;
 *  </pre>
 *  
 *  @see mx.effects.effectClasses.RemoveChildActionInstance
 *  @see mx.states.RemoveChild
 *
 *  @includeExample ../states/examples/TransitionExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class RemoveChildAction extends Effect
{
    include "../core/Version.as";

	//--------------------------------------------------------------------------
	//
	//  Class constants
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private static var AFFECTED_PROPERTIES:Array = [ "parent", "index" ];

	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------

	/**
	 *  Constructor.
	 *
	 *  @param target The Object to animate with this effect.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function RemoveChildAction(target:Object = null)
	{
		super(target);
        duration = 0;
		instanceClass = RemoveChildActionInstance;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Overridden methods
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	override public function getAffectedProperties():Array /* of String */
	{
		return AFFECTED_PROPERTIES;
	}
	
	/**
	 *  @private
	 */
	private function propChangesSortHandler(
					first:PropertyChanges, 
					second:PropertyChanges):Number
	{
		if (first.start.index > second.start.index)
			return 1;
		else if (first.start.index < second.start.index)
			return -1;
		
		return 0;
	}
	
	/**
	 *  @private
	 */
	override mx_internal function applyStartValues(propChanges:Array,
									 		  targets:Array):void
	{
		if (propChanges)
			propChanges.sort(propChangesSortHandler);
		
		super.applyStartValues(propChanges, targets);
	}
	
	/**
	 *  @private
	 */
	override protected function getValueFromTarget(target:Object,
												   property:String):*
	{
		if (property == "index")
			return target.parent ? target.parent.getChildIndex(target) : 0;
		
		return super.getValueFromTarget(target, property);
	}
	
	/**
	 *  @private
	 */	
	override protected function applyValueToTarget(target:Object,
												   property:String, 
												   value:*,
												   props:Object):void
	{
		if (property == "parent" && target.parent == null && value)
			value.addChildAt(target, Math.min(props.index, value.numChildren));
		
		// Ignore index - it's applied along with parent
	}
}

}
