package mx.managers {
    import flash.events.Event;
    import flash.events.EventDispatcher;

    import mx.core.UIComponentGlobals;
    import mx.core.mx_internal;
    import mx.events.FlexEvent;

    import org.flexunit.assertThat;

    import org.flexunit.asserts.assertEquals;
    import org.flexunit.asserts.assertNotNull;
    import org.flexunit.asserts.assertNull;
    import org.flexunit.async.Async;
    import org.fluint.uiImpersonation.UIImpersonator;

    use namespace mx_internal;

    public class LayoutManager_FLEX_35321_Tests
    {
        private static var noEnterFramesRemaining:int = NaN;
        private static const _finishNotifier:EventDispatcher = new EventDispatcher();

        private var _objectWhichIsRemovedAtValidation:SomeComponent;
        private var _creationCompleteCalls:int;

        [Before]
        public function setUp():void
        {
            _creationCompleteCalls = 0;
            _objectWhichIsRemovedAtValidation = new SomeComponent();
            _objectWhichIsRemovedAtValidation.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
            UIImpersonator.addElement(_objectWhichIsRemovedAtValidation);
        }

        [After]
        public function tearDown():void
        {
            UIImpersonator.removeAllChildren();
            _objectWhichIsRemovedAtValidation = null;
        }


        //--------------------------------------------------------------------------
        //
        //  Test method
        //
        //--------------------------------------------------------------------------

        [Test]
        public function test_object_removed_from_stage_via_code_is_not_initialized():void
        {
            //given
            UIComponentGlobals.mx_internal::layoutManager.usePhasedInstantiation = false;
            _objectWhichIsRemovedAtValidation.removeFromStageOnValidateProperties = true;

            //when
            _objectWhichIsRemovedAtValidation.invalidateProperties();
            _objectWhichIsRemovedAtValidation.invalidateSize();
            _objectWhichIsRemovedAtValidation.invalidateDisplayList();
            _objectWhichIsRemovedAtValidation.validateNow();

            //then
            then_assert_not_initialized();
            assert_validation_count(1, 0, 0);
        }



        //--------------------------------------------------------------------------
        //
        //  Test method
        //
        //--------------------------------------------------------------------------

        [Test(async, timeout=500)]
        public function test_object_removed_from_stage_via_user_action_is_not_initialized():void
        {
            //given
            UIComponentGlobals.mx_internal::layoutManager.usePhasedInstantiation = true;
            _objectWhichIsRemovedAtValidation.removeFromStageOnValidateProperties = false;

            //when
            _objectWhichIsRemovedAtValidation.invalidateDisplayList();
            _objectWhichIsRemovedAtValidation.invalidateProperties();
            _objectWhichIsRemovedAtValidation.invalidateSize();

            //then wait 1 frame
            noEnterFramesRemaining = 1;
            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_remove_from_stage_via_callLater, 300, {nextStep:then_assert_not_initialized_but_partially_validated, afterNumFrames:3});
        }




        //--------------------------------------------------------------------------
        //
        //  Test method
        //
        //--------------------------------------------------------------------------

        [Test(async, timeout=750)]
        public function test_object_removed_from_stage_then_readded_is_initialized_once():void
        {
            //given
            UIComponentGlobals.mx_internal::layoutManager.usePhasedInstantiation = true;
            _objectWhichIsRemovedAtValidation.removeFromStageOnValidateProperties = false;

            //when
            _objectWhichIsRemovedAtValidation.invalidateDisplayList();
            _objectWhichIsRemovedAtValidation.invalidateProperties();
            _objectWhichIsRemovedAtValidation.invalidateSize();

            //then wait 1 frame
            noEnterFramesRemaining = 1;
            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_remove_from_stage_via_callLater, 300, {nextStep:then_readd_object, afterNumFrames:1});
        }

        private function then_readd_object(event:Event, passThroughData:Object):void
        {
            //then
            assertNull("The object was actually not removed from stage. Huh?", _objectWhichIsRemovedAtValidation.parent);

            //when
            UIImpersonator.addElement(_objectWhichIsRemovedAtValidation);

            //then wait 3 frames, to make sure validation is done
            noEnterFramesRemaining = 3;
            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_assert_one_initialization_only, 400);
        }

        private function then_assert_one_initialization_only(event:Event, passThroughData:Object):void
        {
            //then
            assertNotNull("The object should be on stage...", _objectWhichIsRemovedAtValidation.parent);
            assertThat("If it's on stage, the nestLevel should be positive", _objectWhichIsRemovedAtValidation.nestLevel > 0);
            assertEquals("When validation is interrupted half-way it should be complete once the object is re-added to stage", 1, _creationCompleteCalls);
            assert_validation_count(2, 2, 1);
        }


        //--------------------------------------------------------------------------
        //
        //  Shared test methods
        //
        //--------------------------------------------------------------------------

        private function then_remove_from_stage_via_callLater(event:Event, passThroughData:Object):void
        {
            //then
            assertEquals("The first validation step should have completed by now", 1, _objectWhichIsRemovedAtValidation.numValidatePropertiesCalls);
            assertEquals("But not validateSize()", 0, _objectWhichIsRemovedAtValidation.numValidateSizeCalls);
            assertEquals("Nor validateDisplayList()", 0, _objectWhichIsRemovedAtValidation.numValidateDisplayListCalls);

            //given
            const whereToGoNext:Function = passThroughData.nextStep as Function;
            const afterHowManyFrames:int = passThroughData.afterNumFrames as int;

            //when
            _objectWhichIsRemovedAtValidation.pretendUserAskedForComponentRemovalInNextFrame();

            //then wait
            noEnterFramesRemaining = afterHowManyFrames;
            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, whereToGoNext, 300);
        }

        private function then_assert_not_initialized(event:Event = null, passThroughData:Object = null):void
        {
            //then
            assertNull("The object was actually not removed from stage. Huh?", _objectWhichIsRemovedAtValidation.parent);
            assertEquals("Yep, this is the bug. Why call initialized=true on an object that's not on stage?", 0, _creationCompleteCalls);
        }

        private function then_assert_not_initialized_but_partially_validated(event:Event = null, passThroughData:Object = null):void
        {
            //then
            then_assert_not_initialized(event, passThroughData);
            assert_validation_count(1, 1, 0);
        }

        private function assert_validation_count(numPropertiesValidations:int = 1, numSizeValidations:int = 1, numDisplayListValidations:int = 1):void
        {
            //then
            assertEquals("Properties should have been validated", numPropertiesValidations, _objectWhichIsRemovedAtValidation.numValidatePropertiesCalls);
            assertEquals("Size should have been validated", numSizeValidations, _objectWhichIsRemovedAtValidation.numValidateSizeCalls);
            assertEquals("Display list should have been validated", numDisplayListValidations, _objectWhichIsRemovedAtValidation.numValidateDisplayListCalls);
        }



        private static function onEnterFrame(event:Event):void
        {
            if(!--noEnterFramesRemaining)
            {
                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
            }
        }

        private function onCreationComplete(event:FlexEvent):void
        {
            _creationCompleteCalls++;
        }
    }
}

import mx.core.IVisualElementContainer;
import mx.core.UIComponent;

class SomeComponent extends UIComponent
{
    private var _removeFromStageOnValidateProperties:Boolean = false;
    private var _numValidatePropertiesCalls:int = 0;
    private var _numValidateSizeCalls:int = 0;
    private var _numValidateDisplayListCalls:int = 0;

    override public function validateProperties():void
    {
        super.validateProperties();
        _numValidatePropertiesCalls++;
        if(_removeFromStageOnValidateProperties)
            removeFromStage();
    }

    override public function validateSize(recursive:Boolean = false):void
    {
        super.validateSize(recursive);
        _numValidateSizeCalls++;
    }

    override public function validateDisplayList():void
    {
        super.validateDisplayList();
        _numValidateDisplayListCalls++;
    }

    private function removeFromStage():void
    {
        if(this.parent)
        {
            if(this.parent is IVisualElementContainer)
                IVisualElementContainer(this.parent).removeElement(this);
            else
                this.parent.removeChild(this);
        }
    }

    public function pretendUserAskedForComponentRemovalInNextFrame():void
    {
        callLater(removeFromStage);
    }

    public function set removeFromStageOnValidateProperties(value:Boolean):void
    {
        _removeFromStageOnValidateProperties = value;
    }

    public function get numValidateDisplayListCalls():int
    {
        return _numValidateDisplayListCalls;
    }

    public function get numValidateSizeCalls():int
    {
        return _numValidateSizeCalls;
    }

    public function get numValidatePropertiesCalls():int
    {
        return _numValidatePropertiesCalls;
    }
}