////////////////////////////////////////////////////////////////////////////////
//
//  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.core
{

import flash.display.DisplayObject;
import flash.events.Event;
import mx.collections.ArrayCollection;
import mx.collections.CursorBookmark;
import mx.collections.ICollectionView;
import mx.collections.IList;
import mx.collections.IViewCursor;
import mx.collections.ItemResponder;
import mx.collections.ListCollectionView;
import mx.collections.XMLListCollection;
import mx.collections.errors.ItemPendingError;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.FlexEvent;
import mx.managers.ISystemManager;
import mx.managers.SystemManager;
import mx.automation.IAutomationObject;

use namespace mx_internal;

//--------------------------------------
//  Events
//--------------------------------------

/**
 *  Dispatched each time an item is processed and the 
 *  <code>currentIndex</code> and <code>currentItem</code> 
 *  properties are updated.
 *
 *  @eventType mx.events.FlexEvent.REPEAT
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="repeat", type="mx.events.FlexEvent")]

/**
 *  Dispatched after all the subcomponents of a repeater are created.
 *  This event is triggered even if the <code>dataProvider</code>
 *  property is empty or <code>null</code>.
 *
 *  @eventType mx.events.FlexEvent.REPEAT_END
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="repeatEnd", type="mx.events.FlexEvent")]

/**
 *  Dispatched when Flex begins processing the <code>dataProvider</code>
 *  property and begins creating the specified subcomponents.
 *  This event is triggered even if the <code>dataProvider</code>
 *  property is empty or <code>null</code>.
 *
 *  @eventType mx.events.FlexEvent.REPEAT_START
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="repeatStart", type="mx.events.FlexEvent")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[IconFile("Repeater.png")]

[ResourceBundle("core")]

/**
 *  The Repeater class is the runtime object that corresponds
 *  to the <code>&lt;mx:Repeater&gt;</code> tag.
 *  It creates multiple instances of its subcomponents
 *  based on its dataProvider.
 *  The repeated components can be any standard or custom
 *  controls or containers.
 *
 *  <p>You can use the <code>&lt;mx:Repeater&gt;</code> tag
 *  anywhere a control or container tag is allowed, with the exception
 *  of the <code>&lt;mx:Application&gt;</code> container tag.
 *  To repeat a user interface component, you place its tag
 *  in the <code>&lt;mx:Repeater&gt;</code> tag.
 *  You can use more than one <code>&lt;mx:Repeater&gt;</code> tag
 *  in an MXML document.
 *  You can also nest <code>&lt;mx:Repeater&gt;</code> tags.</p>
 *
 *  <p>You cannot use the <code>&lt;mx:Repeater&gt;</code> tag
 *  for objects that do not extend the UIComponent class.</p>
 *
 *  @mxml
 *
 *  <p>The &lt;Repeater&gt; class has the following properties:</p>
 *
 *  <pre>
 *  &lt;mx:Repeater
 *    <strong>Properties</strong>
 *    id="<i>No default</i>"
 *    childDescriptors="<i>No default</i>"
 *    count="<i>No default</i>"
 *    dataProvider="<i>No default</i>"
 *    recycleChildren="false|true"
 *    startingIndex="0"
 *
 *    <strong>Events</strong>
 *    repeat="<i>No default</i>"
 *    repeatEnd="<i>No default</i>"
 *    repeatStart="<i>No default</i>"
 *  &gt;
 *  </pre>
 *
 *  @includeExample examples/RepeaterExample.mxml
 *
 *  @see mx.core.Container
 *  @see mx.core.UIComponent
 *  @see mx.core.UIComponentDescriptor
 *  @see flash.events.EventDispatcher
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class Repeater extends UIComponent implements IRepeater
{
    include "../core/Version.as";

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

    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function Repeater()
    {
        super();
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private var iterator:IViewCursor;

    /**
     *  @private
     *  Flag indicating whether this Repeater has been fully created.
     *  Used to avoid createComponentFromDescriptor() calling execute().
     */
    private var created:Boolean = false;

    /**
     *  @private
     *  The index of this Repeater's UIComponentDescriptor in the
     *  container's child descriptors.
     */
    private var descriptorIndex:int;

    /**
     *  @private
     *  The Array of components created during the previous execution.
     *  This array is used during recycle().
     * 
     *  mx_internal for automation delegate access
     */
    mx_internal var createdComponents:Array;

    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  showInAutomationHierarchy
    //----------------------------------

  	/**
     *  @private
     */
    override public function set showInAutomationHierarchy(value:Boolean):void
    {
    	//do not allow value changes
    }

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  childDescriptors
    //----------------------------------

    /**
     *  An Array of UIComponentDescriptor objects for this Repeater's children.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var childDescriptors:Array /* of UIComponentDescriptor */;

    //----------------------------------
    //  container
    //----------------------------------

    /**
     *  @private
     *  Storage for the 'container' read-only property.
     *  Initialized by the constructor.
     */
    private var _container:Container;

    /**
     *  The container that contains this Repeater.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get container():IContainer
    {
        return _container as IContainer;
    }

    //----------------------------------
    //  count
    //----------------------------------

    /**
     *  @private
     *  Storage for the 'count' property.
     */
    private var _count:int = -1;

    [Bindable("countChanged")]
    [Inspectable(category="General", defaultValue="-1")]

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get count():int
    {
        return _count;
    }

    /**
     *  @private
     */
    public function set count(value:int):void
    {
        _count = value;

        execute();

        dispatchEvent(new Event("countChanged"));
    }

    //----------------------------------
    //  currentIndex
    //----------------------------------

    /**
     *  @private
     *  Storage for the 'currentIndex' property.
     */
    private var _currentIndex:int;

    [Bindable("nextRepeaterItem")]
    [Inspectable(category="General", defaultValue="-1")]

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get currentIndex():int
    {
        if (_currentIndex == -1)
        {
			var message:String = resourceManager.getString(
				"core", "notExecuting");
            throw new Error(message);
        }

        return _currentIndex;
    }

    //----------------------------------
    //  currentItem
    //----------------------------------

    [Bindable("nextRepeaterItem")]
    [Inspectable(category="General", defaultValue="null")]

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get currentItem():Object
    {
        if (_currentIndex == -1)
        {
			var message:String = resourceManager.getString(
				"core", "notExecuting");
            throw new Error(message);
        }

        var result:Object;

        if (iterator)
        {
            try
            {
                iterator.seek(CursorBookmark.FIRST, _currentIndex);
                result = iterator.current;
            }
            catch(itemPendingError:ItemPendingError)
            {
                itemPendingError.addResponder(new ItemResponder(responderResultHandler, responderFaultHandler));
            }
        }

        return result;
    }

    //----------------------------------
    //  dataProvider
    //----------------------------------

    /**
     *  @private
     *  Storage for the 'dataProvider' property.
     */
    private var collection:ICollectionView;

    [Bindable("collectionChange")]
    [Inspectable(category="General", defaultValue="null")]

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get dataProvider():Object
    {
        return collection;
    }

    /**
     *  @private
     */
    public function set dataProvider(value:Object):void
    {
        var hadValue:Boolean = false;

        if (collection)
        {
            hadValue = true;
            collection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangedHandler);
            collection = null;
            iterator = null;
        }

        if (value is Array)
        {
            collection = new ArrayCollection(value as Array);
        }
        else if (value is ICollectionView)
        {
            collection = ICollectionView(value);
        }
        else if (value is IList)
        {
            collection = new ListCollectionView(IList(value));
        }
        else if (value is XMLList)
        {
            collection = new XMLListCollection(value as XMLList);
        }
        else if (value is XML)
        {
            var xl:XMLList = new XMLList();
            xl += value;
            collection = new XMLListCollection(xl);
        }
        else if (value != null)
        {
            // convert it to an array containing this one item
            var tmp:Array = [value];
            collection = new ArrayCollection(tmp);
        }

        if (collection)
        {
            // weak reference
            collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangedHandler, false, 0, true);
            iterator = collection.createCursor();
        }

        dispatchEvent(new Event("collectionChange"));

        if (collection || hadValue)
        {
            execute();
        }
    }

    //----------------------------------
    //  numCreatedChildren
    //----------------------------------

    /**
     *  @private
     */
    private function get numCreatedChildren():int
    {
        var result:int = 0;

        for (var i:int = 0; i < createdComponents.length; i++)
        {
            var component:IFlexDisplayObject = createdComponents[i];
            if (component is Repeater)
            {
                var repeater:Repeater = Repeater(component);
                result += repeater.numCreatedChildren;
            }
            else
            {
                result += 1;
            }
        }

        return result;
    }

    //----------------------------------
    //  recycleChildren
    //----------------------------------

    /**
     *  @private
     *  Storage for the recycleChildren property.
     */
    private var _recycleChildren:Boolean = false;

    [Inspectable(category="Other", defaultValue="false")]

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get recycleChildren():Boolean
    {
        return _recycleChildren;
    }

    /**
     *  @private
     */
    public function set recycleChildren(value:Boolean):void
    {
        _recycleChildren = value;
    }

    //----------------------------------
    //  startingIndex
    //----------------------------------

    /**
     *  @private
     *  Storage for the 'startingIndex' property.
     */
    private var _startingIndex:int = 0;

    [Bindable("startingIndexChanged")]
    [Inspectable(category="General", defaultValue="0")]

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get startingIndex():int
    {
        return _startingIndex;
    }

    /**
     *  @private
     */
    public function set startingIndex(value:int):void
    {
        _startingIndex = value;

        execute();

        dispatchEvent(new Event("startingIndexChanged"));
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override public function toString():String
    {
        return Object(container).toString() + "." + super.toString();
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function initializeRepeater(container:IContainer,
                                       recurse:Boolean):void
    {
        _container = Container(container);
        descriptorIndex = container.numChildren;
        created = true;

        // Create instances of the components contained within
        // this Repeater
        if (collection)
        {
            createComponentsFromDescriptors(recurse);
        }
        
        if (owner == null)
        	owner = Container(container);
    }

    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function executeChildBindings():void
    {
        var n:int = container.numChildren;
        for (var i:int = 0; i < n; i++)
        {
            var child:IRepeaterClient = IRepeaterClient(container.getChildAt(i));

            if (hasDescendant(child) && child is IDeferredInstantiationUIComponent)
                IDeferredInstantiationUIComponent(child).executeBindings();
        }
    }

    /**
     *  @private
     *  Used by data binding code generation.
     */
    mx_internal function getItemAt(index:int):Object
    {
        var result:Object;

        if (iterator)
        {
            try
            {
                iterator.seek(CursorBookmark.FIRST, index);
                result = iterator.current;
            }
            catch(itemPendingError:ItemPendingError)
            {
                itemPendingError.addResponder(
                    new ItemResponder(responderResultHandler, responderFaultHandler));
            }
        }

        return result;
    }

    /**
     *  @private
     */
    private function responderResultHandler(data:Object, info:Object):void
    {
        execute();
    }

    /**
     *  @private
     */
    private function responderFaultHandler(data:Object, info:Object):void
    {
    }

    /**
     *  @private
     *  Determines whether the specified UIComponent or Repeater
     *  is inside this Repeater, by searching its 'repeaters' array.
     *
     *  The methods removeAllChildren() and removeAllChildRepeaters()
     *  use this to determine which child UIComponents and child Repeaters
     *  of this Repeater's container should be removed, since some of
     *  the container's children may be outside this Repeater.
     */
    private function hasDescendant(o:Object):Boolean
    {
        var repeaters:Array = o.repeaters;
        if (repeaters == null)
            return false;

        var n:int = repeaters.length;
        for (var i:int = 0; i < n; i++)
        {
            if (repeaters[i] == this)
                return true;
        }
        return false;
    }

    /**
     *  @private
     *  Removes all the child UIComponents in this Repeater's container
     *  which belong to this Repeater. Returns the lowest index of the
     *  removed children, or null if none were removed.
     *
     *  The method execute() uses this to clean up previously created
     *  child UIComponents when this Repeater's dataProvider, startingIndex,
     *  or count changes.
     */
    private function removeAllChildren(container:IContainer):void
    {
        // It's simpler and more efficient
        // to loop backwards when removing children.
        var n:int = container.numChildren;
        for (var i:int = n - 1; i >= 0; i--)
        {
            var child:IRepeaterClient = IRepeaterClient(container.getChildAt(i));

            if (hasDescendant(child))
            {
                if (child is Container)
                {
                    removeAllChildren(Container(child));
                    removeAllChildRepeaters(Container(child));
                }

                container.removeChildAt(i);

                if (child is IDeferredInstantiationUIComponent)
                {
                    IDeferredInstantiationUIComponent(child).
                        deleteReferenceOnParentDocument(
                            IFlexDisplayObject(parentDocument));
                }
            }
        }
    }

    /**
     *  @private
     *  Removes all the child Repeaters in this Repeater's container
     *  which belong to this Repeater.
     *
     *  The method execute() uses this to clean up previously created
     *  child Repeaters when this Repeater's dataProvider, startingIndex,
     *  or count changes.
     */
    private function removeAllChildRepeaters(container:Container):void
    {
        // It's simpler and more efficient
        // to loop backwards when removing repeaters.
        if (container.childRepeaters)
        {
            var n:int = container.childRepeaters.length;
            for (var i:int = n - 1; i >= 0; i--)
            {
                var repeater:Repeater = container.childRepeaters[i];
                if (hasDescendant(repeater))
                {
                    removeRepeater(repeater);
                }
            }
        }
    }

    /**
     *  @private
     */
    private function removeChildRepeater(container:Container, repeater:Repeater):void
    {
        var i:int = 0;
        var n:int = container.childRepeaters.length;

        while (i < n)
        {
            if (container.repeaters[i] == repeater)
            {
                container.repeaters.splice(i, 1);
                break;
            }
            i++;
        }
    }

    /**
     *  @private
     */
    private function createComponentFromDescriptor(
                                    instanceIndex:int,
                                    descriptorIndex:int,
                                    recurse:Boolean):IFlexDisplayObject
    {
        var descriptor:UIComponentDescriptor = childDescriptors[descriptorIndex];

        if (!descriptor.document)
        {
            descriptor.document = document;
        }

        // Ensure that the newly created component gets the proper
        // 'instanceIndices', 'repeaters' and 'repeaterIndices'
        // properties.
        descriptor.instanceIndices = instanceIndices ? instanceIndices : [];
        descriptor.instanceIndices.push(instanceIndex)
        descriptor.repeaters = repeaters;
        descriptor.repeaters.push(this);
        descriptor.repeaterIndices = repeaterIndices;
        descriptor.repeaterIndices.push(startingIndex + instanceIndex);

        // Do not reuse the descriptor's properties, because we don't want repeated items
        // to share non scalar properties.  Otherwise they will have references to the
        // same objects as opposed to having their own instances.
        descriptor.invalidateProperties();

        // Create object described by the descriptor (which might be
        // either a UIComponent or a nested Repeater).
        var child:IFlexDisplayObject = Container(container).createComponentFromDescriptor(
                                                descriptor, recurse);

        // get rid of the repeater-specific properties on the
        // descriptor now that createComponent is done
        descriptor.instanceIndices = null;
        descriptor.repeaters = null;
        descriptor.repeaterIndices = null;

        // Execute any binding that is watching the current item.
        dispatchEvent(new Event("nextRepeaterItem"));

        return child;
    }

    /**
     *  @private
     *  Create repeated instances of the UIComponents and Repeaters
     *  that are owned by this Repeater, based on its dataProvider.
     *
     *  This method is the heart of the Repeater class. It is called
     *  when this repeater is created by createComponentFromDescriptor(),
     *  and when this Repeater gets re-executed when its dataProvider,
     *  startingIndex, or count changes.
     */
    private function createComponentsFromDescriptors(recurse:Boolean):void
    {
        dispatchEvent(new FlexEvent(FlexEvent.REPEAT_START));

        createdComponents = [];

        if (collection && (collection.length > 0) && (collection.length - startingIndex > 0))
        {
            var n:int = positiveMin(collection.length - startingIndex, count);

            // Loop over the items of the dataProvider.
            for (var i:int = 0; i < n; i++)
            {
                // When a repeater is repeating, 'currentIndex' and 'currentItem'
                // can be read.
                _currentIndex = startingIndex + i;

                // Dispatch a "repeat" event.
                dispatchEvent(new FlexEvent(FlexEvent.REPEAT));

                if (childDescriptors && (childDescriptors.length > 0))
                {
                    var m:int = childDescriptors.length;

                    // Loop over the child descriptors of the repeater.
                    for (var j:int = 0; j < m; j++)
                    {
                        var component:IFlexDisplayObject =
                            createComponentFromDescriptor(i, j, recurse);

                        createdComponents.push(component);

                        if (component is IUIComponent)
                        	 IUIComponent(component).owner = this;

                        if (component is IAutomationObject)
                        	 IAutomationObject(component).showInAutomationHierarchy = true;
                    }
                }
            }

            // When a repeater isn't repeating, 'currentIndex' is -1
            // and 'currentItem' is null.
            _currentIndex = -1;
        }

        dispatchEvent(new FlexEvent(FlexEvent.REPEAT_END));
    }

    /**
     *  @private
     *  This method is used by execute() to determine where the newly-created
     *  UIComponents should be inserted in the container.
     */
    private function getIndexForFirstChild():int
    {
        var locationInfo:LocationInfo = new LocationInfo();
        var i:int = 0;
        var cc:Array = Container(container).createdComponents;
        var length:int = cc ? cc.length : 0;

        while (i < length)
        {
            var component:IFlexDisplayObject = Container(container).createdComponents[i];

            if (component == this)
            {
                locationInfo.found = true;
                break;
            }
            else if (component is Repeater)
            {
                var repeater:Repeater = Repeater(component);
                repeater.getIndexForRepeater(this, locationInfo);

                if (locationInfo.found)
                {
                    break;
                }
            }
            else
            {
                locationInfo.index += 1;
            }

            i++;
        }

        return locationInfo.found ? locationInfo.index : container.numChildren;
    }

    /**
     *  @private
     */
    private function getIndexForRepeater(target:Repeater,
                                         locationInfo:LocationInfo):void
    {
        var i:int = 0;
        var length:int = createdComponents.length;

        while (i < length)
        {
            var component:IFlexDisplayObject = createdComponents[i];

            if (component == target)
            {
                locationInfo.found = true;
                break;
            }
            else if (component is Repeater)
            {
                var repeater:Repeater = Repeater(component);
                repeater.getIndexForRepeater(target, locationInfo);

                if (locationInfo.found)
                    break;
            }
            else
            {
                locationInfo.index += 1;
            }

            i++;
        }
    }

    /**
     *  @private
     *  This method is used by execute() to move the newly-created UIComponents,
     *  which get created at the end of the container, to their proper indexes
     *  in the container.
     */
    private function reindexDescendants(from:int, to:int):void
    {
        // Determine how many children were created by
        // createComponentsFromDescriptors(), which includes the
        // children created by nested Repeaters in this container.
        var n:int = container.numChildren - from;

        // Set the child index of each one.
        for (var i:int = 0; i < n; i++)
        {
            var child:IRepeaterClient =
                IRepeaterClient(container.getChildAt(from + i));

            container.setChildIndex(DisplayObject(child), to + i);
        }
    }

    /**
     *  @private
     */
    private function resetRepeaterIndices(o:IRepeaterClient, index:int):void
    {
        var repeaterIndices:Array = o.repeaterIndices;
        repeaterIndices[repeaterIndices.length - 1] = index;
        o.repeaterIndices = repeaterIndices;

        if (o is Container)
        {
            var fc:Container = Container(o);

            var n:int = fc.numChildren;
            for (var i:int = 0; i < n; i++)
            {
                var child:IRepeaterClient = IRepeaterClient(fc.getChildAt(i));

                resetRepeaterIndices(child, index);
            }
        }
    }

    /**
     *  @private
     */
    private function recycle():void
    {
        dispatchEvent(new FlexEvent(FlexEvent.REPEAT_START));

        var n:int = 0;
        var i:int;
        var m:int;
        var j:int;

        var numComponents:int = 0;

        if (collection && (collection.length > 0) && (collection.length - startingIndex > 0))
        {
            n = positiveMin(collection.length - startingIndex, count);

            var previousChildIndex:int = 0;

            // Loop over the items of the dataProvider.
            for (i = 0; i < n; i++)
            {
                // When a repeater is repeating, 'currentIndex' and 'currentItem'
                // can be read.
                _currentIndex = startingIndex + i;

                // Dispatch a "repeat" event.
                dispatchEvent(new FlexEvent(FlexEvent.REPEAT));

                if (childDescriptors)
                {
                    m = childDescriptors.length;
                    var repeater:Repeater;

                    if (createdComponents.length >= ((i + 1) * m))
                    {
                        // Loop over the components previously created by this Repeater
                        for (j = 0; j < m; j++)
                        {
                            var createdComponent:IRepeaterClient = createdComponents[(i * m) + j];

                            if (createdComponent is Repeater)
                            {
                                repeater = Repeater(createdComponent);
                                resetRepeaterIndices(repeater, _currentIndex);
				                repeater.owner = this;
                                repeater.execute();
                            }
                            else
                            {
                                resetRepeaterIndices(createdComponent, _currentIndex);
                                if (createdComponent is IDeferredInstantiationUIComponent)
                                    IDeferredInstantiationUIComponent(createdComponent).executeBindings(true);
                            }
                            numComponents++;
                        }
                    }
                    else
                    {
                        for (j = 0; j < m; j++)
                        {
                            var from:int = container.numChildren;
                            var to:int = getIndexForFirstChild() + numCreatedChildren;

                            var component:IRepeaterClient =
                                IRepeaterClient(createComponentFromDescriptor(i, j, true));

                            createdComponents.push(component);

                            if (component is IUIComponent)
                                IUIComponent(component).owner = this;
                            
                            if (component is IAutomationObject)
                                IAutomationObject(component).showInAutomationHierarchy = true;

                            if (component is Repeater)
                            {
                                repeater = Repeater(component);
                                repeater.reindexDescendants(from, to);
                            }
                            else
                            {
                                container.setChildIndex(DisplayObject(component), to);
                            }
                            numComponents++;
                        }
                    }
                }
            }
        }

        // When a repeater isn't repeating, 'currentIndex' is -1 and
        // 'currentItem' is null.
        _currentIndex = -1;

        // Remove any extra children created the last time that we no
        // longer need.
        for (i = createdComponents.length - 1; i >= numComponents; i--)
        {
            var extra:IRepeaterClient = createdComponents.pop();

            if (extra is Repeater)
            {
                removeRepeater(Repeater(extra));
            }
            else if (extra)
            {
                if (extra is Container)
                {
                    removeAllChildren(Container(extra));
                    removeAllChildRepeaters(Container(extra));
                }

                if (container.contains(DisplayObject(extra)))
                    container.removeChild(DisplayObject(extra));

                if (extra is IDeferredInstantiationUIComponent)
                {
                    IDeferredInstantiationUIComponent(extra).
                        deleteReferenceOnParentDocument(
                            IFlexDisplayObject(parentDocument));
                }
            }
        }

        dispatchEvent(new FlexEvent(FlexEvent.REPEAT_END));
    }

    /**
     *  @private
     */
    private function recreate():void
    {
        // Clean out what this Repeater created last time.
        removeAllChildren(container);
        removeAllChildRepeaters(Container(container));

        // Determine how to re-index the new children.
        var from:int = container.numChildren;
        var to:int = getIndexForFirstChild();

        // Create new child UIComponents and child Repeaters.
        // The child UIComponents get added at the "end"
        // of the container by addChild().
        createComponentsFromDescriptors(true);

        // Re-index them to where they belong.
        if (from != to)
            reindexDescendants(from, to);
    }

    /**
     *  @private
     *  Execute this Repeater a second time, after its dataProvider,
     *  startingIndex, or count changes.
     */
    private function execute():void
    {
        if (!created)
            return;

        if (recycleChildren && createdComponents && (createdComponents.length > 0))
            recycle();
        else
            recreate();
    }

    /**
     *  @private
     *  Handles "Change" event sent by calls to Collection APIs
     *  on this Repeater's dataProvider.
     */
    private function collectionChangedHandler(collectionEvent:CollectionEvent):void
    {
        switch (collectionEvent.kind)
        {
            case CollectionEventKind.UPDATE:
            {
                break;
            }

            default:
            {
                execute();
            }
        }
    }

    /**
     *  @private
     */
    private function addItems(firstIndex:int, lastIndex:int):void
    {
        if (startingIndex > lastIndex)
            return;

        var i:int;

        // Determine the child index at which the newly created
        // components will be inserted.
        var index:int = -1;
        var n:int = container.numChildren;
        var child:IRepeaterClient;
        var repeaterIndex:int;

        // If the data items have just been appended to the dataProvider,
        // loop over the children of the container in reverse order,
        // looking for the first child that was associated with this
        // repeater. We'll insert the newly created components after
        // that child.
        if (lastIndex == (collection.length - 1))
        {
            for (i = n - 1; i >= 0; i--)
            {
                child = IRepeaterClient(container.getChildAt(i));
                repeaterIndex = getRepeaterIndex(child);

                if (repeaterIndex != -1)
                {
                    index = i + 1;
                    break;
                }
            }
        }

        // If the data items have just been inserted before the end
        // of the dataProvider, loop over the the children of the container,
        // looking for the first one in the specified range.
        // For example, if items 3 through 5 were just inserted,
        // look for the first child that previously was
        // associated with item 3, 4, or 5.
        else
        {
            var numItemsAdded:int = (lastIndex - firstIndex) + 1;
            for (i = 0; i < n; i++)
            {
                child = IRepeaterClient(container.getChildAt(i));
                repeaterIndex = getRepeaterIndex(child);

                if (repeaterIndex != -1)
                {
                    if (firstIndex <= repeaterIndex &&
                        repeaterIndex <= lastIndex &&
                        index == -1)
                    {
                        index = i;
                    }

                    if (repeaterIndex >= firstIndex)
                        adjustIndices(child, numItemsAdded);
                }
            }
        }

        // Create components for the new dataProvider items
        if (count == -1)
        {
            n = lastIndex;
        }
        else
        {
            n = positiveMin(startingIndex + count - 1, lastIndex);
        }

        for (i = Math.max(startingIndex, firstIndex); i <= n; i++)
        {
            var m:int = childDescriptors.length;

            _currentIndex = i;
            dispatchEvent(new FlexEvent(FlexEvent.REPEAT));

            for (var j:int = 0; j < m; j++)
            {
                var from:int = container.numChildren;
                var to:int = getIndexForFirstChild() + numCreatedChildren;
                var component:IFlexDisplayObject =
                    createComponentFromDescriptor(i - startingIndex, j, true);

                createdComponents.push(component);

                if (component is IUIComponent)
                    IUIComponent(component).owner = this;

                if (component is IAutomationObject)
                	 IAutomationObject(component).showInAutomationHierarchy = true;
                
                // The newly created components are at the end of the container.
                // Move them to the indexes where they belong.
                if (component is Repeater)
                {
                    var r:Repeater = Repeater(component);
					r.owner = this;
                    r.reindexDescendants(from, to);
                }
                else
                {
                    container.setChildIndex(DisplayObject(component), to);
                }
            }
        }

        _currentIndex = -1;
    }

    /**
     *  @private
     */
    private function removeItems(firstIndex:int, lastIndex:int):void
    {
        if (createdComponents && (createdComponents.length > 0))
        {
            for (var i:int = createdComponents.length - 1; i >= 0; i--)
            {
                var component:IRepeaterClient = createdComponents[i];

                var repeaterIndex:int = getRepeaterIndex(component);

                if (((firstIndex <= repeaterIndex) &&
                    ((repeaterIndex < lastIndex) || (lastIndex == -1))) ||
                    (repeaterIndex >= dataProvider.length))
                {
                    if (component is Repeater)
                    {
                        var repeater:Repeater = Repeater(component);
                        removeRepeater(repeater);
                    }
                    else if (container.contains(DisplayObject(component)))
                    {
                        container.removeChild(DisplayObject(component));
                    }

                    if (component is IDeferredInstantiationUIComponent)
                    {
                        IDeferredInstantiationUIComponent(component).
                            deleteReferenceOnParentDocument(
                                IFlexDisplayObject(parentDocument));
                    }

                    createdComponents.splice(i, 1);
                }
                else if ((firstIndex <= repeaterIndex) && (lastIndex != -1) &&
                         (repeaterIndex >= lastIndex))
                {
                    adjustIndices(component, (lastIndex - firstIndex) + 1);

                    if (component is IDeferredInstantiationUIComponent)
                    {
                        IDeferredInstantiationUIComponent(component).
                            executeBindings(true);
                    }
                }
            }
        }
    }

    /**
     *  @private
     */
    private function removeRepeater(repeater:Repeater):void
    {
        repeater.removeAllChildren(repeater.container);

        repeater.removeAllChildRepeaters(Container(repeater.container));

        removeChildRepeater(Container(container), repeater);

        repeater.deleteReferenceOnParentDocument(
            IFlexDisplayObject(parentDocument));

        // Null out the dataProvider, so that listeners will be removed.
        repeater.dataProvider = null;
    }

    /**
     *  @private
     */
    private function updateItems(firstIndex:int, lastIndex:int):void
    {
        if (recycleChildren)
        {
            var n:int = container.numChildren;
            for (var i:int = 0; i < n; i++)
            {
                var child:IRepeaterClient = IRepeaterClient(container.getChildAt(i));
                var repeaterIndex:int = getRepeaterIndex(child);

                if (repeaterIndex != -1 &&
                    firstIndex <= repeaterIndex &&
                    repeaterIndex <= lastIndex)
                {
                    if (child is IDeferredInstantiationUIComponent)
                        IDeferredInstantiationUIComponent(child).executeBindings(true);
                }
            }
        }
        else
        {
            removeItems(firstIndex, lastIndex);
            addItems(firstIndex, lastIndex);
        }
    }

    /**
     *  @private
     */
    private function sort():void
    {
        execute();
    }

    /**
     *  @private
     */
    private function getRepeaterIndex(o:IRepeaterClient):int
    {
        var repeaters:Array = o.repeaters;
        if (repeaters == null)
            return -1;

        var n:int = repeaters.length;
        for (var i:int = 0; i < n; i++)
        {
            if (repeaters[i] == this)
                return o.repeaterIndices[i];
        }

        return -1;
    }

    /**
     *  @private
     */
    private function adjustIndices(o:IRepeaterClient, adjustment:int):void
    {
        var repeaters:Array = o.repeaters;
        if (repeaters == null)
            return;

        var n:int = repeaters.length;
        for (var i:int = 0; i < n; i++)
        {
            if (repeaters[i] == this)
            {
                o.repeaterIndices[i] += adjustment;
                o.instanceIndices[i] += adjustment;
                break;
            }
        }
    }

    /**
     *  @private
     *  This function is like Math.min(),
     *  but if x is negative, it is ignored.
     *  If y is negative, it is ignored.
     *  If both are negative, zero is returned.
     */
    private function positiveMin(x:int, y:int):int
    {
        var result:int = 0;

        if (x >= 0)
        {
            if (y >= 0)
            {
                if (x < y)
                    result = x;
                else
                    result = y;
            }
            else
            {
                result = x;
            }
        }
        else
        {
            result = y;
        }

        return result;
    }

}

}

////////////////////////////////////////////////////////////////////////////////

/**
 *  @private
 */
class LocationInfo
{
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    public function LocationInfo()
    {
        super();
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    public var found:Boolean = false;

    /**
     *  @private
     */
    public var index:int = 0;
}
