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

import flash.events.EventDispatcher;
import flash.utils.Dictionary;
import flash.xml.XMLNode;

import mx.collections.errors.ItemPendingError;
import mx.core.EventPriority;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.PropertyChangeEvent;
import mx.utils.IXMLNotifiable;
import mx.utils.UIDUtil;
import mx.utils.XMLNotifier;

use namespace mx_internal;

/**
 *  The HierarchicalCollectionView class provides a hierarchical view of a standard collection.
 *
 *  @mxml
 *
 *  The <code>&lt;mx.HierarchicalCollectionView&gt;</code> inherits all the tag attributes of its superclass, 
 *  and defines the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;mx:HierarchicalCollectionView
 *  <b>Properties </b>
 *    showRoot="true|false"
 *    source="<i>No default</i>"
 *  /&gt;
 *  </pre> 
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class HierarchicalCollectionView extends EventDispatcher
                                        implements IHierarchicalCollectionView, IXMLNotifiable
{
    include "../core/Version.as";
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *
     *  @param hierarchicalData The data structure containing the hierarchical data.
     *
     *  @param argOpenNodes The Object that defines a node to appear as open.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function HierarchicalCollectionView(
                            hierarchicalData:IHierarchicalData = null,
                            argOpenNodes:Object = null)
    {
        super();
        
        if (hierarchicalData)
            initializeCollection(hierarchicalData.getRoot(), hierarchicalData, argOpenNodes);
    }
    
    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    private var hierarchicalData:IHierarchicalData;

    /**
     *  @private
     *  The total number of nodes we know about.
     */
    private var currentLength:int;
    
    /**
     *  @private
     *  Top level XML node if there is one
     */
    private var parentNode:XML;

    /**
     *  @private
     *  Mapping of nodes to children.  Used by getChildren.
     */
    private var childrenMap:Dictionary;
    
    /**
     *  @private
     */
    private var childrenMapCache:Dictionary = new Dictionary(true);
    
    /**
     *  @private
     */
    mx_internal var treeData:ICollectionView;
    
    /**
     *  @private
     *  Mapping of UID to parents.  Must be maintained as things get removed/added
     *  This map is created as objects are visited
     */
    private var parentMap:Object;

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

    //----------------------------------
    //  hasRoot
    //----------------------------------
    
    private var _hasRoot:Boolean;
    
    /** 
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get hasRoot():Boolean
    {
        return _hasRoot;
    }
    
    //----------------------------------
    //  openNodes
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the openNodes property.
     */
    private var _openNodes:Object;
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get openNodes():Object
    {
        return _openNodes;  
    }
    
    /**
     *  @private
     */
    public function set openNodes(value:Object):void
    {
        // openNodes cant be null
        if (value)
        {
            _openNodes = {};
            for each (var item:* in value)
            {
                _openNodes[UIDUtil.getUID(item)] = item;
            }
        }
        else
            _openNodes = {};
        
        if (hierarchicalData)
        {
            //calc initial length
            currentLength = calculateLength();
            
            // need to refresh the collection after setting openNodes
            var event:CollectionEvent =
                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
            event.kind = CollectionEventKind.REFRESH;
            dispatchEvent(event);
        }
    }
    
    //----------------------------------
    //  showRoot
    //----------------------------------
    
    private var _showRoot:Boolean = true;
    
    [Bindable]
    [Inspectable(category="Data", enumeration="true,false", defaultValue="true")]
    
    /**
     *  @inheritDoc
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get showRoot():Boolean
    {
        return _showRoot;
    }

    /**
     *  @private
     */
    public function set showRoot(value:Boolean):void
    {
        if (_showRoot != value)
        {
            _showRoot = value;
            if (hierarchicalData)
            {
                initializeCollection(hierarchicalData.getRoot(), hierarchicalData, openNodes);
                
                //setting showRoot resets the collection
                var event:CollectionEvent =
                    new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
                event.kind = CollectionEventKind.RESET;
                dispatchEvent(event);
            }
        }
    }
    
    //----------------------------------
    //  source
    //----------------------------------
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get source():IHierarchicalData
    {
        return hierarchicalData;
    }

    /**
     *  @private
     */
    public function set source(value:IHierarchicalData):void
    {
        initializeCollection(value.getRoot(), value, openNodes);
    }
    
    //----------------------------------
    //  filter
    //----------------------------------

    /**
     *  @private
     *  Storage for the filterFunction property.
     */
    private var _filterFunction:Function;

    [Bindable("filterFunctionChanged")]
    [Inspectable(category="General")]
    
    /**
     *  @private
     */
    public function get filterFunction():Function
    {
        return _filterFunction;
    }

    /**
     *  @private
     */
    public function set filterFunction(value:Function):void
    {
        _filterFunction = value;
    }

    //----------------------------------
    //  length
    //----------------------------------

    /**
     *  The length of the currently parsed collection (i.e. the number
     *  of nodes that can be accessed by navigating the collection via
     *  HierarchicalCollectionViewCursor)
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get length():int
    {
        return currentLength;
    }

    //----------------------------------
    //  sort
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the sort property.
     */
    private var _sort:ISort;

    [Bindable("sortChanged")]
    [Inspectable(category="General")]
    
    /**
     *  @private
     */
    public function get sort():ISort
    {
        return _sort;
    }

    /**
     *  @private
     */
    public function set sort(value:ISort):void
    {
        _sort = value;
    }
    
    //--------------------------------------------------------------------------
    //
    // ICollectionView Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Returns a new instance of a view iterator over the items in this view.
     *
     *  @return IViewCursor instance.
     *
     *  @see mx.collections.IViewCursor
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function createCursor():IViewCursor
    {
        return new HierarchicalCollectionViewCursor(
            this, treeData, hierarchicalData);
    }

    /**
     *  Checks the collection for the data item using standard equality test.
     *
     *  @param item The Object that defines the node to look for.
     *
     *  @param <code>true</code> if the collection contains the item,
     *
     *  @return <code>true</code> if the data item is in the collection, 
     *  and <code>false</code> if not.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function contains(item:Object):Boolean
    {
        var cursor:IViewCursor = createCursor();
        while (!cursor.afterLast)
        {
            if (cursor.current == item)
                return true;
                
            try
            {
                cursor.moveNext();
            }
            catch (e:ItemPendingError)
            {
                // item is pending.
                // we are not sure if the item is present or not, 
                // so return false
                return false;
            }
        }
        return false;
    }

    /**
     *  @private
     */
    public function disableAutoUpdate():void
    {
        // propogate to all the child collections
        treeData.disableAutoUpdate();
        for (var p:Object in childrenMap)
            ICollectionView(childrenMap[p]).disableAutoUpdate();
    }

    /**
     *  @private
     */
    public function enableAutoUpdate():void
    {
        // propogate to all the child collections
        treeData.enableAutoUpdate();
        for (var p:Object in childrenMap)
            ICollectionView(childrenMap[p]).enableAutoUpdate();
    }

    /**
     *  @private
     */
    public function itemUpdated(item:Object, property:Object = null,
                                oldValue:Object = null,
                                newValue:Object = null):void
    {
        var event:CollectionEvent =
            new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
        event.kind = CollectionEventKind.UPDATE;

        var objEvent:PropertyChangeEvent =
            new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
        objEvent.source = item;
        objEvent.property = property;
        objEvent.oldValue = oldValue;
        objEvent.newValue = newValue;
        event.items.push(objEvent);

        dispatchEvent(event);
    }
    
    /**
     *  @inheritDoc 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function refresh():Boolean
    {   
        return internalRefresh(true);
    }
    
    //--------------------------------------------------------------------------
    //
    // IHierarchicalCollectionView Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     * @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */ 
    public function getNodeDepth(node:Object):int
    {
        var depth:int = 1;
        var parent:Object = getParentItem(node);
        
        while(parent != null)
        {
            parent = getParentItem(parent);
            depth++;
        }
        depth = (hasRoot && !showRoot) ? (depth - 1) : depth;
        
        // depth cant be less then 1
        return (depth < 1) ? 1 : depth;
    }
    
    /**
     *  Returns the parent of a node.  
     *  The parent of a top-level node is <code>null</code>.
     *
     *  @param node The Object that defines the node.
     *
     *  @return The parent node containing the node, 
     *  <code>null</code> for a top-level node,  
     *  and <code>undefined</code> if the parent cannot be determined.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function getParentItem(node:Object):*
    {
        var uid:String = UIDUtil.getUID(node);
        if (parentMap.hasOwnProperty(uid))
            return parentMap[uid];

        return undefined;
    }

    public function deleteParentMapping(uid:String):void
    {
        delete parentMap[uid];
    }

    public function addParentMapping(uid:String, parent:Object, replaceExisting:Boolean = true):void
    {
        if(replaceExisting || !parentMap.hasOwnProperty(uid))
            parentMap[uid] = parent;
    }
    
    /**
     *  @inheritDoc 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function getChildren(node:Object):ICollectionView
    {
        // Using uid because XML cant be referenced correctly using Dictionary
        var uid:String = UIDUtil.getUID(node);
        var children:* = hierarchicalData.getChildren(node);
        
        var childrenCollection:ICollectionView = childrenMapCache[uid];
        
        if (children is XMLList && childrenCollection)
        {       
            //We don't want to send a RESET type of collectionChange event in this case. 
            XMLListCollection(childrenCollection).mx_internal::dispatchResetEvent = false; 
            XMLListCollection(childrenCollection).source = children;
            
            // refresh the collection to apply the sort/filter
            childrenCollection.refresh();
        }
        
        // check the cache and return from it.
        // useful in sorting/filtering.
        if(childrenCollection)
        {
            // node might have changed, so update the childrenMap
            childrenMap[node] = childrenCollection;
            return childrenCollection;
        }
        
        // if there is no children, return null
        if (!children)
            return null;
        
        //then wrap children in ICollectionView if necessary
        if (children is ICollectionView)
        {
            childrenCollection = ICollectionView(children);
        }
        else if (children is Array)
        {
            childrenCollection = new ArrayCollection(children);
        }
        else if (children is XMLList)
        {
            childrenCollection =  new XMLListCollection(children);
        }
        else
        {
            var childArray:Array = new Array(children);
            if (childArray != null)
            {
                childrenCollection =  new ArrayCollection(childArray);
            }
        }
        
        childrenMapCache[uid] = childrenCollection;
        
        
        var oldChildren:ICollectionView = childrenMap[node];
        if (oldChildren != childrenCollection)
        {
            if (oldChildren != null)
            {
                oldChildren.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
                                      nestedCollectionChangeHandler);
            }
            childrenCollection.addEventListener(CollectionEvent.COLLECTION_CHANGE,
                                          nestedCollectionChangeHandler, false, 0, true);
            childrenMap[node] = childrenCollection;
        }
        
        return childrenCollection;
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function openNode(node:Object):void
    {
        var uid:String = UIDUtil.getUID(node);
        
        // check if the node is already opened
        if (_openNodes[uid] != null)
            return;

        // check if the node is accessible, abort if not
        var parent:* = getParentItem(node);
        while(parent)
        {
            parent = getParentItem(parent);
        }

        //undefined means an ancestor is not open, which means the node is inaccessible
        if(parent === undefined)
            return;

        // add the node to the openNodes object and update the length
        _openNodes[uid] = node;
        
        // apply the sort/filter to the child collection of the opened node.
        var childrenCollection:ICollectionView = getChildren(node);
        
        // return if there are no children
        if (!childrenCollection)
            return;
        
        if (sortCanBeApplied(childrenCollection) && !(childrenCollection.sort == null && sort == null))
        {
            childrenCollection.sort = this.sort;
        }
        if (!(childrenCollection.filterFunction == null && filterFunction == null))
        {
            childrenCollection.filterFunction = this.filterFunction;
        }
        childrenCollection.refresh();

        updateParentMapAndLength(childrenCollection, node);
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function closeNode(node:Object):void
    {
        var childrenCollection:ICollectionView = childrenMap[node];

        // removes the node from the openNodes object and update the length
        delete _openNodes[UIDUtil.getUID(node)];

        if (childrenCollection)
        {
            var cursor:IViewCursor = childrenCollection.createCursor();
            while (!cursor.afterLast)
            {
                var uid:String = UIDUtil.getUID(cursor.current);
                deleteParentMapping(uid);

                try
                {
                    cursor.moveNext();
                }
                catch (e:ItemPendingError)
                {
                    break;
                }
        
            }
        }
        
        // update the length
        updateLength();
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function addChild(parent:Object, newChild:Object):Boolean
    {
        if (parent == null)
            return addChildAt(parent, newChild, treeData.length);
        else
            return addChildAt(parent, newChild, getChildren(parent).length);
    }

    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function removeChild(parent:Object, child:Object):Boolean
    {
        var cursor:IViewCursor;
        if (parent == null)
        {
            cursor = treeData.createCursor();
        }
        else
        {
             var children:ICollectionView = getChildren(parent);
             cursor = children.createCursor();
        }
        while (!cursor.afterLast)
        {
            if (cursor.current == child)
            {
                cursor.remove();
                return true;
            }
                
            try
            {
                cursor.moveNext();
            }
            catch (e:ItemPendingError)
            {
                // Items are pending - so return false
                return false;
            }
        }
        
        return false;
    }
    
    /**
     *  Add a child node to a node at the specified index. 
     *  This implementation does the following:
     * 
     *  <ul>
     *      <li>If the <code>parent</code> is null or undefined,
     *          inserts the <code>child</code> at the 
     *          specified <code>index</code> in the collection specified 
     *          by <code>source</code>.
     *      </li>
     *      <li>If the <code>parent</code> has a <code>children</code>
     *          field or property, the method adds the <code>child</code> 
     *          to it at the <code>index</code> location.
     *          In this case, the <code>source</code> is not required.
     *     </li>
     *     <li>If the <code>parent</code> does not have a <code>children</code>
     *          field or property, the method adds the <code>children</code> 
     *          to the <code>parent</code>. The method then adds the 
     *          <code>child</code> to the parent at the 
     *          <code>index</code> location. 
     *          In this case, the <code>source</code> is not required.
     *     </li>
     *     <li>If the <code>index</code> value is greater than the collection 
     *         length or number of children in the parent, adds the object as
     *         the last child.
     *     </li>
     * </ul>
     *
     *  @param parent The Object that defines the parent node.
     * 
     *  @param newChild The Object that defines the child node.
     * 
     *  @param index The 0-based index of where to insert the child node.
     *
     *  @return <code>true</code> if the child is added successfully.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function addChildAt(parent:Object, newChild:Object, index:int):Boolean
    {   
        var cursor:IViewCursor;
        if (!parent)
        {
            cursor = treeData.createCursor();
        }
        else
        {
            if (!hierarchicalData.canHaveChildren(parent))
                return false;
            
            var children:ICollectionView = getChildren(parent);
            
            cursor = children.createCursor();
        }
        
        try
        {
            cursor.seek(CursorBookmark.FIRST, index);
        }
        catch (e:ItemPendingError)
        {
            // Item Pending
            return false;
        }
        
        cursor.insert(newChild);
        
        return true;
    }

    /**
     *  Removes the child node from a node at the specified index.
     *
     *  @param parent The Object that defines the parent node.
     * 
     *  @param index The 0-based index of  the child node to remove relative to the parent.
     * 
     *  @return <code>true</code> if the child is removed successfully.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function removeChildAt(parent:Object, index:int):Boolean
    {
        var cursor:IViewCursor;
        if (!parent)
        {
            cursor = treeData.createCursor();
        }
        else
        {
            var children:ICollectionView = getChildren(parent);
            cursor = children.createCursor();
        }
        
        try
        {
            cursor.seek(CursorBookmark.FIRST, index);
        }
        catch (e:ItemPendingError)
        {
            // Item Pending
            return false;
        }
        
        if (cursor.beforeFirst || cursor.afterLast)
            return false;
        
        cursor.remove();
        return true;
    }
    
    //--------------------------------------------------------------------------
    //
    // Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     * @private
     * 
     * returns the collection view of the given object
     */ 
    private function getCollection(value:Object):ICollectionView
    {
        // handle strings and xml
        if (typeof(value)=="string")
            value = new XML(value);
        else if (value is XMLNode)
            value = new XML(XMLNode(value).toString());
        else if (value is XMLList)
            value = new XMLListCollection(value as XMLList);
        
        if (value is XML)
        {
            var xl:XMLList = new XMLList();
            xl += value;
            return new XMLListCollection(xl);
        }
        //if already a collection dont make new one
        else if (value is ICollectionView)
        {
            return ICollectionView(value);
        }
        else if (value is Array)
        {
            return new ArrayCollection(value as Array);
        }
        //all other types get wrapped in an ArrayCollection
        else if (value is Object)
        {         
            // convert to an array containing this one item
            var tmp:Array = [];
            tmp.push(value);
            return new ArrayCollection(tmp);
        }
        else
        {
            return new ArrayCollection();
        }
    }
    
    /**
     *  @private
     *  
     *  Initialize the collection. set its various properties and
     *  update its length.
     */
    private function initializeCollection(model:Object,
                            hierarchicalData:IHierarchicalData,
                            argOpenNodes:Object = null):void
    {
        parentMap = {};

        childrenMap = new Dictionary(true);
        childrenMapCache = new Dictionary(true);
        
        if (treeData)
            treeData.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
                                         collectionChangeHandler,
                                         false);
        
        if (this.hierarchicalData)
            this.hierarchicalData.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
                                         collectionChangeHandler,
                                         false);
        
        treeData = getCollection(model);
        
        if (treeData)
            _hasRoot = treeData.length == 1;
        
        var tmpCollection:Object = model;
        // are we swallowing the root?
        if (hierarchicalData && !showRoot && hasRoot)
        {
            var obj:Object = treeData.createCursor().current;
            if (hierarchicalData.hasChildren(obj))
            {
                // then get rootItem children
                tmpCollection = hierarchicalData.getChildren(obj);
                treeData = getCollection(tmpCollection);
            }
        }

        // listen for add/remove events from developer as weak reference
        treeData.addEventListener(CollectionEvent.COLLECTION_CHANGE,
                                  collectionChangeHandler,
                                  false,
                                  EventPriority.DEFAULT_HANDLER,
                                  true);
                                  
        this.hierarchicalData = hierarchicalData;
        
        // listen for reset/refresh events
        this.hierarchicalData.addEventListener(
                                    CollectionEvent.COLLECTION_CHANGE,
                                    collectionChangeHandler,
                                    false,
                                    EventPriority.DEFAULT_HANDLER,
                                    true);
        
        // openNodes cant be null
        if (argOpenNodes)
            _openNodes = argOpenNodes;
        else
            _openNodes = {};
        
        //calc initial length
        currentLength = calculateLength();
    }
    
    /**
     *  @private
     *  
     *  Update the parent map and adjust the length.
     */ 
    private function updateParentMapAndLength(collection:ICollectionView, node:Object):void
    {
        var cursor:IViewCursor = collection.createCursor();
        currentLength += collection.length;
        
        while (!cursor.afterLast)
        {
            var item:Object = cursor.current;
            var uid:String = UIDUtil.getUID(item);
            addParentMapping(uid, node);
            
            // check that the node is opened or not.
            // If it is open, then update the length with the node's children.
            if (_openNodes[uid] != null)
            {
                var childrenCollection:ICollectionView = getChildren(item);
                if (childrenCollection)
                    updateParentMapAndLength(childrenCollection, item);
            }
            
            try
            {
                cursor.moveNext();
            }
            catch (e:ItemPendingError)
            {
                break;
            }
        }
    }
    
    /**
     *  @private
     *  Calculate the total length of the collection, but only count nodes
     *  that we can reach.
     */
    public function calculateLength(node:Object = null, parent:Object = null):int
    {
        var length:int = 0;
        var childNodes:ICollectionView;
        var modelOffset:int = 0;
        var firstNode:Boolean = true;

        if (node == null)
        {
            // special case counting the whole thing
            // watch for page faults
            var modelCursor:IViewCursor = treeData.createCursor();
            if (modelCursor.beforeFirst)
            {
                // indicates that an IPE occured on the first item
                return treeData.length;
            }
            while (!modelCursor.afterLast)
            {
                node = modelCursor.current;
                if (node is XML)
                {
                    if (firstNode)
                    {   
                        firstNode = false;
                        var parNode:* = node.parent();
                        if (parNode != null)
                        {
                            startTrackUpdates(parNode);
                            childrenMap[parNode] = treeData;
                            parentNode = parNode;
                        }
                    }
                    startTrackUpdates(node);
                }
                if (node === null)
                    length += 1;
                else
                    length += calculateLength(node, null) + 1;
                modelOffset++;
                try
                {
                    modelCursor.moveNext();
                }
                catch (e:ItemPendingError)
                {
                    // just stop where we are, no sense paging
                    // the whole thing just to get length. make a rough
                    // guess assuming that all un-paged nodes are closed
                    length += treeData.length - modelOffset;
                    return length;
                }
            }
        }
        else
        {
            var uid:String = UIDUtil.getUID(node);
            addParentMapping(uid, parent);
            if (node != null &&
                openNodes[uid] &&
                hierarchicalData.canHaveChildren(node) &&
                hierarchicalData.hasChildren(node))
            {
                childNodes = getChildren(node);
                if (childNodes != null)
                {
                    var childCursor:IViewCursor = childNodes.createCursor();
                    try
                    {
                        childCursor.seek(CursorBookmark.FIRST);
                        while (!childCursor.afterLast)
                        {
                            if (node is XML)
                                startTrackUpdates(childCursor.current);
                            length += calculateLength(childCursor.current, node) + 1;
                            modelOffset++;
                            
                            try
                            {
                                childCursor.moveNext();
                            }
                            catch (e:ItemPendingError)
                            {
                                // just stop where we are, no sense paging
                                // the whole thing just to get length. make a rough
                                // guess assuming that all un-paged nodes are closed
                                length += childNodes.length - modelOffset;
                                return length;
                            }
                        }
                    }
                    catch (e:ItemPendingError)
                    {
                        // assume that the child collection has one item
                        length += 1;
                    }
                }
            }
        }
        return length;
    }
    
    /**
     *  @private
     */
    private function internalRefresh(dispatch:Boolean):Boolean
    {
        var obj:Object;
        var coll:ICollectionView;
        var needUpdate:Boolean = false;
        
        // apply filter function to all the collections including the child collections
        if (!(treeData.filterFunction == null && filterFunction == null))
        {
            treeData.filterFunction = filterFunction;
            treeData.refresh();
            needUpdate = true;
        }
        
        for each(obj in openNodes)
        {
            coll = getChildren(obj);
            if (coll && !(coll.filterFunction == null && filterFunction == null))
            {
                coll.filterFunction = filterFunction;
                coll.refresh();
                needUpdate = true
            }
        }
        
        // if filter is applied to any collection, only then update the length
        if (needUpdate)
            updateLength();  // length will change after filtering, so update it.
        
        
        // apply sort to all the collections including the child collections
        if (sortCanBeApplied(treeData) && !(treeData.sort == null && sort == null))
        {
            treeData.sort = sort;
            treeData.refresh();
            dispatch = true;
        }
        
        // recursive sort for every field
        for each(obj in openNodes)
        {
            
            coll = getChildren(obj);
            
            if (coll && sortCanBeApplied(coll) && !(coll.sort == null && sort == null))
            {
                coll.sort = sort;
                coll.refresh();
                dispatch = true;
            }
        }
        
        // No concept of a sort level, so commenting the code
        /* for(var i:int = 0;i<sort.fields.length;i++)
        {
            if(sort.fields[i].hasOwnProperty("sortLevel"))
                sortLevel = sort.fields[i].sortLevel;
            //else
                //sortLevel = 1;
            
            
            if(sortLevel == 1)
            {
                var srt:ISort = new Sort();
                        
                if(sort.usingCustomCompareFunction)
                {
                    srt.compareFunction = sort.compareFunction;
                }
                
                srt.unique = sort.unique;
                        
                srt.fields = [sort.fields[i]];
                treeData.sort = srt;
                treeData.refresh();
            }
            else
            {
                for each(var obj:Object in openNodes)
                {
                    
                    var depth:int = 2;
                    var o:Object = obj;
                    while(getParentItem(o) != null)
                    {
                        depth++;
                        o = getParentItem(o);
                    }
                    
                    if(depth == sortLevel)
                    {
                        var coll:ICollectionView = getChildren(obj);
                        
                        var srt:ISort = new Sort();
                        
                        if(sort.usingCustomCompareFunction)
                            srt.compareFunction = sort.compareFunction;
                        
                        srt.unique = sort.unique;
                        
                        srt.fields = [sort.fields[i]];
                        
                        coll.sort = srt;
                        coll.refresh();
                    }
                }
            }
        } */
            
        if (dispatch)
        {
            var refreshEvent:CollectionEvent =
                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
            refreshEvent.kind = CollectionEventKind.REFRESH;
            dispatchEvent(refreshEvent);
        }
        return true;
    }
    
    /**
     * @private
     * Check if a collection has the properties on which the sort is applied.   
     */
    private function sortCanBeApplied(coll:ICollectionView):Boolean
    {
        if (sort == null)
            return true;
        
        // get the current item
        var obj:Object = coll.createCursor().current;
        
        if (!obj || !sort.fields)
            return false;
        
        // check for the properties (sort fields) in the current object
        for (var i:int = 0; i < sort.fields.length; i++)
        {
            var sf:SortField = sort.fields[i];
            if (!obj.hasOwnProperty(sf.name))
                return false;
        }
        return true;
    }
    
    /**
     * @private
     * Force a recalculation of length
     */
     private function updateLength():void
     {
        currentLength = calculateLength();
     }

    /**
     * @private
     *  Fill the node array with the node and all of its visible children
     *  update the parentMap as you go.
     */
    private function getVisibleNodes(node:Object, parent:Object, nodeArray:Array):void
    {
        var childNodes:ICollectionView;
        nodeArray.push(node);

        var uid:String = UIDUtil.getUID(node);
        addParentMapping(uid, parent);
        if (openNodes[uid] != null &&
            hierarchicalData.canHaveChildren(node) &&
            hierarchicalData.hasChildren(node))
        {
            childNodes = getChildren(node);
            if (childNodes != null)
            {
                var cursor:IViewCursor = childNodes.createCursor();
                while (!cursor.afterLast)
                {
                    getVisibleNodes(cursor.current, node, nodeArray);
                    try
                    {
                        cursor.moveNext();
                    }
                    catch (e:ItemPendingError)
                    {
                        // Items are pending - so return
                        return;
                    }
                }
            }
        }
    }

    /**
     *  @private
     *  Factor in the available open children before this location in the model
     */
    private function getVisibleLocation(oldLocation:int):int
    {
        var newLocation:int = 0;
        var modelCursor:IViewCursor = treeData.createCursor();
        for (var i:int = 0; i < oldLocation && !modelCursor.afterLast; i++)
        {
            newLocation += calculateLength(modelCursor.current, null) + 1;
            try
            {
                modelCursor.moveNext();
            }
            catch (e:ItemPendingError)
            {
                // just return the location as the items are pending
                return newLocation;
            }
        }
        return newLocation;
    }

    /**
     * @private
     * factor in the open children before this location in a sub collection
     */
    private function getVisibleLocationInSubCollection(parent:Object, oldLocation:int):int
    {
        var newLocation:int = oldLocation;
        var target:Object = parent;
        parent = getParentItem(parent);
        var children:ICollectionView;
        var cursor:IViewCursor;
        while (parent != null)
        {
            children = childrenMap[parent];
            cursor = children.createCursor();
            while (!cursor.afterLast)
            {
                if (cursor.current == target)
                {
                    newLocation++;
                    break;
                }
                newLocation += calculateLength(cursor.current, parent) + 1;
                try
                {
                    cursor.moveNext();
                }
                catch (e:ItemPendingError)
                {
                    break;
                }
            }
            target = parent;
            parent = getParentItem(parent);
        }
        cursor = treeData.createCursor();
        while (!cursor.afterLast)
        {
            if (cursor.current == target)
            {
                newLocation++;
                break;
            }
            newLocation += calculateLength(cursor.current, parent) + 1;
            try
            {
                cursor.moveNext();
            }
            catch (e:ItemPendingError)
            {
                break;
            }
        }
        return newLocation;
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    public function collectionChangeHandler(event:CollectionEvent):void
    {
        var i:int;
        var n:int;
        var node:Object;

        var convertedEvent:CollectionEvent;
        
        if (event is CollectionEvent)
        {
            var ce:CollectionEvent = CollectionEvent(event);
            if (ce.kind == CollectionEventKind.REFRESH)
            {
                // collection refreshed, update length
                updateLength();
            }
            else if (ce.kind == CollectionEventKind.RESET)
            {
                // initialize the collection again - its source is modified
                if (hierarchicalData)
                    initializeCollection(hierarchicalData.getRoot(), hierarchicalData, openNodes);
                updateLength();
                internalRefresh(false);
                dispatchEvent(event);
            }
            else if (ce.kind == CollectionEventKind.ADD)
            {
                n = ce.items.length;
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        ce.kind);
                convertedEvent.location = getVisibleLocation(ce.location);
                for (i = 0; i < n; i++)
                {
                    node = ce.items[i];
                    if (node is XML)
                        startTrackUpdates(node);
                    getVisibleNodes(node, null, convertedEvent.items);
                }
                currentLength += convertedEvent.items.length;
                dispatchEvent(convertedEvent);
            }
            else if (ce.kind == CollectionEventKind.REMOVE)
            {
                n = ce.items.length;
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        ce.kind);
                convertedEvent.location = getVisibleLocation(ce.location);
                for (i = 0; i < n; i++)
                {
                    node = ce.items[i];
                    if (node is XML)
                        stopTrackUpdates(node);
                    getVisibleNodes(node, null, convertedEvent.items);
                }

                currentLength -= convertedEvent.items.length;

                dispatchEvent(convertedEvent);

                n = convertedEvent.items.length;
                for (i = 0; i < n; i++)
                {
                    deleteParentMapping(UIDUtil.getUID(convertedEvent.items[i]));
                }
            }
            else if (ce.kind == CollectionEventKind.UPDATE)
            {
                // so far, nobody cares about the details so just
                // send it
                dispatchEvent(event);
            }
            else if (ce.kind == CollectionEventKind.REPLACE)
            {
                // someday handle case where node is marked as open
                // before it becomes the replacement.
                // for now, just pass on the data and remove
                // old visible rows
                n = ce.items.length;
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        CollectionEventKind.REMOVE);

                for (i = 0; i < n; i++)
                {
                    node = ce.items[i].oldValue;
                    if (node is XML)
                        stopTrackUpdates(node);
                    getVisibleNodes(node, null, convertedEvent.items);
                }

                // prune the replacements from this list
                for (i = 0; i < n; i++)
                {
                    node = ce.items[i].oldValue;
                    var replacedNodePosition:int = convertedEvent.items.indexOf(node);
                    if(replacedNodePosition != -1)
                        convertedEvent.items.splice(replacedNodePosition, 1);
                }
                if (convertedEvent.items.length)
                {
                    currentLength -= convertedEvent.items.length;
                    // nobody cares about location yet.
                    dispatchEvent(convertedEvent);
                }
                dispatchEvent(event);
            }
        }
    }

    /**
     *  @private
     */
    public function nestedCollectionChangeHandler(event:CollectionEvent):void
    {
        var i:int;
        var n:int;
        var parentOfChangingNode:Object;
        var changingNode:Object;
        var convertedEvent:CollectionEvent;

        if (event is CollectionEvent)
        {
            var ce:CollectionEvent = CollectionEvent(event);
            if (ce.kind == CollectionEventKind.mx_internal::EXPAND)
            {
                event.stopImmediatePropagation();
            }
            else if (ce.kind == CollectionEventKind.ADD)
            {
                // optimize someday.  We do a full tree walk so we can
                // not only count how many but find the parents of the
                // new nodes.  A better scheme would be to just
                // increment by the number of visible nodes, but we
                // don't have a good way to get the parents.
                updateLength();
                n = ce.items.length;
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        ce.kind);
                for (i = 0; i < n; i++)
                {
                    changingNode = ce.items[i];
                    if (changingNode is XML)
                        startTrackUpdates(changingNode);
                    parentOfChangingNode = getParentItem(changingNode);
                    if (parentOfChangingNode != null)
                        getVisibleNodes(changingNode, parentOfChangingNode, convertedEvent.items);
                }
                convertedEvent.location = getVisibleLocationInSubCollection(parentOfChangingNode, ce.location);
                dispatchEvent(convertedEvent);
            }
            else if (ce.kind == CollectionEventKind.REMOVE)
            {
                n = ce.items.length;
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        ce.kind);
                for (i = 0; i < n; i++)
                {
                    changingNode = ce.items[i];
                    if (changingNode is XML)
                        stopTrackUpdates(changingNode);
                    parentOfChangingNode = getParentItem(changingNode);
                    if (parentOfChangingNode != null)
                        getVisibleNodes(changingNode, parentOfChangingNode, convertedEvent.items);
                }
                convertedEvent.location = getVisibleLocationInSubCollection(parentOfChangingNode, ce.location);
                currentLength -= convertedEvent.items.length;
                dispatchEvent(convertedEvent);
            }
            else if (ce.kind == CollectionEventKind.UPDATE)
            {
                // so far, nobody cares about the details so just
                // send it
                dispatchEvent(event);
            }
            else if (ce.kind == CollectionEventKind.REPLACE)
            {
                // someday handle case where node is marked as open
                // before it becomes the replacement.
                // for now, just pass on the data and remove
                // old visible rows
                n = ce.items.length;
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        CollectionEventKind.REMOVE);

                for (i = 0; i < n; i++)
                {
                    changingNode = ce.items[i].oldValue;
                    parentOfChangingNode = getParentItem(changingNode);
                    
                    if (parentOfChangingNode != null)
                    {
                        getVisibleNodes(changingNode, parentOfChangingNode, convertedEvent.items);
                        // update the parent of the new item only 
                        // if the parent node is opened
                        if (_openNodes[UIDUtil.getUID(parentOfChangingNode)] != null)
                        {
                            addParentMapping(UIDUtil.getUID(ce.items[i].newValue), parentOfChangingNode);
                        }
                    }
                }

                // prune the replacements from this list
                for (i = 0; i < n; i++)
                {
                    changingNode = ce.items[i].oldValue;
                    if (changingNode is XML)
                        stopTrackUpdates(changingNode);

                    var replacedNodePosition:int = convertedEvent.items.indexOf(changingNode);
                    if(replacedNodePosition != -1)
                        convertedEvent.items.splice(replacedNodePosition, 1);
                }
                if (convertedEvent.items.length)
                {
                    currentLength -= convertedEvent.items.length;
                    // nobody cares about location yet.
                    dispatchEvent(convertedEvent);
                }
                dispatchEvent(event);

                for (i = 0; i < n; i++)
                {
                    changingNode = ce.items[i].oldValue;
                    parentOfChangingNode = getParentItem(changingNode);

                    if (parentOfChangingNode != null && _openNodes[UIDUtil.getUID(parentOfChangingNode)] != null)
                        deleteParentMapping(UIDUtil.getUID(changingNode));
                }
            }
            else if (ce.kind == CollectionEventKind.RESET)
            {
                // removeAll() sends a RESET.
                // when we get a reset we don't know what went away
                // and we don't know how many things went away, so
                // we just fake a refresh as if there was a filter
                // applied that filtered out whatever went away
                updateLength();
                convertedEvent = new CollectionEvent(
                                        CollectionEvent.COLLECTION_CHANGE,
                                        false, 
                                        true,
                                        CollectionEventKind.REFRESH);
                dispatchEvent(convertedEvent);
            }
        }
    }
    
    /**
     *  @private
     *  Called whenever an XML object contained in a list is updated
     *  in some way.  The initial implementation stab is very lenient,
     *  any changeType will cause an update no matter how much further down
     *  in a hierarchy.  
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function xmlNotification(currentTarget:Object, 
                                        type:String, 
                                        target:Object, 
                                        value:Object, 
                                        detail:Object):void
    {
        var children:XMLListCollection;
        var location:int;
        var event:CollectionEvent;
        var list:XMLListAdapter;
        
        // trace("currentTarget", currentTarget.toXMLString());
        // trace("target", target.toXMLString());
        // trace("value", value.toXMLString());
        // trace("type", type);

        if (currentTarget === target)
        {
            switch(type)
            {
                case "nodeAdded":
                {
                    for (var q:* in childrenMap)
                    {
                        if (q === currentTarget)
                        {
                            list = childrenMap[q].list as XMLListAdapter;
                            if (list && !list.busy())
                            {
                                if (childrenMap[q] === treeData)
                                {
                                    children = treeData as XMLListCollection;
                                    if (parentNode != null)
                                    {
                                        children.mx_internal::dispatchResetEvent = false;
                                        children.source = parentNode.*;
                                        children.refresh();
                                    }
                                }
                                else
                                {
                                    // this should refresh the collection
                                    children = getChildren(q) as XMLListCollection; 
                                }
                                if (children)
                                {
                                    // now we fake an event on behalf of the
                                    // child collection
                                    location = value.childIndex();
                                    event = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
                                    event.kind = CollectionEventKind.ADD;
                                    event.location = location;
                                    event.items = [ value ];
                                    children.dispatchEvent(event);
                                }
                            }
                            break;
                        }
                    }
                    break;
                }

                /* needed?
                case "nodeChanged":
                {
                    prop = value.localName();
                    oldValue = detail;
                    newValue = value;
                    break;
                }
                */

                case "nodeRemoved":
                {
                    // lookup doesn't work, must scan instead
                    for (var p:* in childrenMap)
                    {
                        if (p === currentTarget)
                        {
                            children = childrenMap[p];
                            list = children.list as XMLListAdapter;
                            if (list && !list.busy())
                            {
                                var xmllist:XMLList = children.source as XMLList;

                                if (childrenMap[p] === treeData)
                                {
                                    children = treeData as XMLListCollection;
                                    if (parentNode)
                                    {
                                        children.mx_internal::dispatchResetEvent = false;
                                        children.source = parentNode.*;
                                        children.refresh();
                                    }
                                }
                                else
                                {
                                    var oldChildren:XMLListCollection = children;
                                    // this should refresh the collection
                                    children = getChildren(p) as XMLListCollection;
                                    if (!children)
                                    {
                                        // last item got removed so there's no child collection
                                        oldChildren.addEventListener(CollectionEvent.COLLECTION_CHANGE,
                                                                      nestedCollectionChangeHandler, false, 0, true);

                                        event = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
                                        event.kind = CollectionEventKind.REMOVE;
                                        event.location = 0;
                                        event.items = [ value ];
                                        oldChildren.dispatchEvent(event);
                                        oldChildren.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
                                                                      nestedCollectionChangeHandler);

                                    }
                                }
                                if (children)
                                {
                                    var n:int = xmllist.length();
                                    for (var i:int = 0; i < n; i++)
                                    {
                                        if (xmllist[i] === value)
                                        {
                                            event = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
                                            event.kind = CollectionEventKind.REMOVE;
                                            event.location = location;
                                            event.items = [ value ];
                                            children.dispatchEvent(event);
                                            break;
                                        }
                                    }
                                }
                            }
                            break;
                        }
                    }
                    break;
                }

                default:
                {
                    break;
                }
            }
        }
    }

    /** 
     *  This is called by addItemAt and when the source is initially
     *  assigned.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    private function startTrackUpdates(item:Object):void
    {
        XMLNotifier.getInstance().watchXML(item, this);
    }
    
    /** 
     *  This is called by removeItemAt, removeAll, and before a new
     *  source is assigned.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    private function stopTrackUpdates(item:Object):void
    {
        XMLNotifier.getInstance().unwatchXML(item, this);
    }
}

}
