/// <summary>
        /// Compares 2 hierarchies for changes:<br/>
        /// 1. Additions<br/>
        /// 2. Removals<br/>
        /// 3. TopLevelRemovals<br/>
        /// 4. Moves<br/>
        /// 5. Renamings<br/>
        /// <br/>
        /// Detailed:<br/>
        /// 1. Additions: When something is added to a hierarchy while in play mode, we have to add it again after the play mode stopped<br/>
        /// We have to do through each added component in chield hierarchy and add it (TODO: what to do with prefabs?)<br/>
        /// 3. Removals: we have to remove persisted data from the list IMMEDIATELLY while still in play mode<br/>
        /// 2. TopLevelRemovals: We have to remove only the TOP components or containers when play mode STOPPED.<br/>
        /// Meaning, if we removed the panel with children while in play mode it will be recreated <br/>
        /// after the play mode is stopped, including all the children. We should remove only the parent.<br/>
        /// </summary>
        /// <param name="oldNode"></param>
        /// <param name="newNode"></param>
        /// <returns></returns>
        public static Delta Compare(Node oldNode, Node newNode)
        {
            Delta delta = new Delta();
            //Process(oldNode, newNode, ref delta);

            var oldList = oldNode.ToList();
            var newList = newNode.ToList();

            /**
             * 1. Raw removals = all removed transforms (including children)
             * */
            var removals = FindMissing(oldList, newList);
            //Debug.Log("### Removals: " + removals.Count);

            /**
             * 2. Top level removals
             * Ignore children if parent in the list -> this is giving us top containers being removed
             * */
            var topLevelRemovals = removals.FindAll(delegate(Node node) // all nodes NOT having the parent node in the list
            {
                //return true; // TEMP
                return !removals.Contains(node.ParentNode);
            });
            
            // Important: we want to process removals bottom-up (from children to parent)
            removals.Reverse();

            /**
             * 3. Delta
             * */
            delta.Removals = removals;
            delta.TopLevelRemovals = topLevelRemovals;

            /**
             * ############ ADDITIONS ############
             * */

            /**
             * 1. Raw additions = all added transforms (including children)
             * */
            var additions = FindMissing(newList, oldList);
            
            /**
             * 2. Top level additions
             * Ignore children if parent in the list -> this is giving us top containers being added
             * */
            var topLevelAdditions = additions.FindAll(delegate(Node node) // all nodes NOT having the parent node in the list
            {
                /**
                 * Note: there was an error before the 20130612
                 * Instead of only the top level additions, all the additions were processed
                 * So it turned out that each sub-collection of the added prefab is being re-scanned, thus overwriting the order saved with a prefab
                 * Only the top-level additions needs to be processed
                 */

                //return true; // TEMP
                return !additions.Contains(node.ParentNode); // 20130612
            });

            /**
             * 3. Delta
             * */
            delta.Additions = additions;
            delta.TopLevelAdditions = topLevelAdditions;

            /**
             * ############ MOVES ############
             * */

            /**
             * 1. Building the list of old list candidates (all nodes in the old list that are NOT REMOVED)
             * */
            var candidatesInTheOldList = oldList.FindAll(delegate(Node node)
                                  {
                                      return !removals.Contains(node);
                                  });

            /**
             * 2. Building the list of new list candidates (all the nodes in the new list that are NOT ADD)
             * */
            var moves = newList.FindAll(delegate(Node node)
            {
                Node oldSnapshot = candidatesInTheOldList.Find(delegate(Node on)
                                                               {
                                                                   return on.Transform == node.Transform;
                                                               });

                var changed = !additions.Contains(node) && node.HasChangedParent(oldSnapshot);

                if (changed)
                {
                    node.OldParentTransform = oldSnapshot.ParentTransform;
                }

                return changed;
            });

            /**
             * 3. Delta
             * */
            delta.Moves = moves;

            /**
             * ############ RENAMINGS ############
             * */

            delta.Renamings = FindRenamed(oldList, newList);

            return delta;
        }