/*
 * 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 org.apache.qpid.server.model.testmodels.lifecycle;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import com.google.common.util.concurrent.ListenableFuture;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.IllegalStateTransitionException;
import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.State;
import org.apache.qpid.test.utils.QpidTestCase;

public class AbstractConfiguredObjectTest extends QpidTestCase
{

    public void testOpeningResultsInErroredStateWhenResolutionFails() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnPostResolve(true);
        object.open();
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ERRORED, object.getState());

        object.setThrowExceptionOnPostResolve(false);
        object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
        assertTrue("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ACTIVE, object.getState());
    }

    public void testOpeningInERROREDStateAfterFailedOpenOnDesiredStateChangeToActive() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnOpen(true);
        object.open();
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ERRORED, object.getState());

        object.setThrowExceptionOnOpen(false);
        object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
        assertTrue("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ACTIVE, object.getState());
    }

    public void testOpeningInERROREDStateAfterFailedOpenOnStart() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnOpen(true);
        object.open();
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ERRORED, object.getState());

        object.setThrowExceptionOnOpen(false);
        object.start();
        assertTrue("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ACTIVE, object.getState());
    }

    public void testDeletionERROREDStateAfterFailedOpenOnDelete() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnOpen(true);
        object.open();
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ERRORED, object.getState());

        object.delete();
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.DELETED, object.getState());
    }

    public void testDeletionInERROREDStateAfterFailedOpenOnDesiredStateChangeToDelete() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnOpen(true);
        object.open();
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ERRORED, object.getState());

        object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.DELETED));
        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.DELETED, object.getState());
    }


    public void testCreationWithExceptionThrownFromValidationOnCreate() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnValidationOnCreate(true);
        try
        {
            object.create();
            fail("IllegalConfigurationException is expected to be thrown");
        }
        catch(IllegalConfigurationException e)
        {
            //pass
        }
        assertFalse("Unexpected opened", object.isOpened());
    }

    public void testCreationWithoutExceptionThrownFromValidationOnCreate() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnValidationOnCreate(false);
        object.create();
        assertTrue("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.ACTIVE, object.getState());
    }

    public void testCreationWithExceptionThrownFromOnOpen() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnOpen(true);
        try
        {
            object.create();
            fail("Exception should have been re-thrown");
        }
        catch (RuntimeException re)
        {
            // pass
        }

        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.DELETED, object.getState());
    }

    public void testCreationWithExceptionThrownFromOnCreate() throws Exception
    {
        TestConfiguredObject object = new TestConfiguredObject(getName());
        object.setThrowExceptionOnCreate(true);
        try
        {
            object.create();
            fail("Exception should have been re-thrown");
        }
        catch (RuntimeException re)
        {
            // pass
        }

        assertFalse("Unexpected opened", object.isOpened());
        assertEquals("Unexpected state", State.DELETED, object.getState());
    }

    public void testUnresolvedChildInERROREDStateIsNotValidatedOrOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
    {
        TestConfiguredObject parent = new TestConfiguredObject("parent");
        TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
        child1.registerWithParents();
        TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
        child2.registerWithParents();

        child1.setThrowExceptionOnPostResolve(true);

        parent.open();

        assertTrue("Parent should be resolved", parent.isResolved());
        assertTrue("Parent should be validated", parent.isValidated());
        assertTrue("Parent should be opened", parent.isOpened());
        assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());

        assertTrue("Child2 should be resolved", child2.isResolved());
        assertTrue("Child2 should be validated", child2.isValidated());
        assertTrue("Child2 should be opened", child2.isOpened());
        assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());

        assertFalse("Child2 should not be resolved", child1.isResolved());
        assertFalse("Child1 should not be validated", child1.isValidated());
        assertFalse("Child1 should not be opened", child1.isOpened());
        assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
    }

    public void testUnvalidatedChildInERROREDStateIsNotOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
    {
        TestConfiguredObject parent = new TestConfiguredObject("parent");
        TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
        child1.registerWithParents();
        TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
        child2.registerWithParents();

        child1.setThrowExceptionOnValidate(true);

        parent.open();

        assertTrue("Parent should be resolved", parent.isResolved());
        assertTrue("Parent should be validated", parent.isValidated());
        assertTrue("Parent should be opened", parent.isOpened());
        assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());

        assertTrue("Child2 should be resolved", child2.isResolved());
        assertTrue("Child2 should be validated", child2.isValidated());
        assertTrue("Child2 should be opened", child2.isOpened());
        assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());

        assertTrue("Child1 should be resolved", child1.isResolved());
        assertFalse("Child1 should not be validated", child1.isValidated());
        assertFalse("Child1 should not be opened", child1.isOpened());
        assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
    }

    public void testSuccessfulStateTransitionInvokesListener() throws Exception
    {
        TestConfiguredObject parent = new TestConfiguredObject("parent");
        parent.create();

        final AtomicReference<State> newState = new AtomicReference<>();
        final AtomicInteger callCounter = new AtomicInteger();
        parent.addChangeListener(new AbstractConfigurationChangeListener()
        {
            @Override
            public void stateChanged(final ConfiguredObject<?> object, final State old, final State state)
            {
                super.stateChanged(object, old, state);
                callCounter.incrementAndGet();
                newState.set(state);
            }
        });

        parent.delete();
        assertEquals(State.DELETED, newState.get());
        assertEquals(1, callCounter.get());
    }

    public void testUnsuccessfulStateTransitionDoesNotInvokesListener() throws Exception
    {
        final IllegalStateTransitionException expectedException =
                new IllegalStateTransitionException("This test fails the state transition.");
        TestConfiguredObject parent = new TestConfiguredObject("parent")
        {
            @Override
            protected ListenableFuture<Void> doDelete()
            {
                throw expectedException;
            }
        };
        parent.create();

        final AtomicInteger callCounter = new AtomicInteger();
        parent.addChangeListener(new AbstractConfigurationChangeListener()
        {
            @Override
            public void stateChanged(final ConfiguredObject<?> object, final State old, final State state)
            {
                super.stateChanged(object, old, state);
                callCounter.incrementAndGet();
            }

            @Override
            public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
            {
                super.attributeSet(object, attributeName, oldAttributeValue, newAttributeValue);
                callCounter.incrementAndGet();
            }
        });

        try
        {
            parent.delete();
            fail("Exception not thrown.");
        }
        catch (RuntimeException e)
        {
            assertSame("State transition threw unexpected exception.", expectedException, e);
        }
        assertEquals(0, callCounter.get());
        assertEquals(State.ACTIVE, parent.getDesiredState());
        assertEquals(State.ACTIVE, parent.getState());
    }


    public void testSuccessfulDeletion() throws Exception
    {
        TestConfiguredObject configuredObject = new TestConfiguredObject("configuredObject");
        configuredObject.create();

        final List<ChangeEvent> events = new ArrayList<>();
        configuredObject.addChangeListener(new AbstractConfigurationChangeListener()
        {
            @Override
            public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
            {
                events.add(new ChangeEvent(EventType.ATTRIBUTE_SET, object, attributeName, oldAttributeValue, newAttributeValue));
            }

            @Override
            public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
            {
                events.add(new ChangeEvent(EventType.STATE_CHANGED, object, ConfiguredObject.DESIRED_STATE, oldState, newState));
            }
        });

        configuredObject.delete();
        assertEquals(2, events.size());
        assertEquals(State.DELETED, configuredObject.getDesiredState());
        assertEquals(State.DELETED, configuredObject.getState());

        assertEquals("Unexpected events number", 2, events.size());
        ChangeEvent event0 = events.get(0);
        ChangeEvent event1 = events.get(1);

        assertEquals("Unexpected first event: " + event0,
                new ChangeEvent(EventType.STATE_CHANGED, configuredObject, Exchange.DESIRED_STATE, State.ACTIVE, State.DELETED), event0 );
        assertEquals("Unexpected second event: " + event1,
                new ChangeEvent(EventType.ATTRIBUTE_SET, configuredObject, Exchange.DESIRED_STATE, State.ACTIVE, State.DELETED), event1 );
    }

    private enum EventType
    {
        ATTRIBUTE_SET,
        STATE_CHANGED
    }

    private class ChangeEvent
    {
        private final ConfiguredObject<?> _source;
        private final String _attributeName;
        private final Object _oldValue;
        private final Object _newValue;
        private final EventType _eventType;

        public ChangeEvent(EventType eventType, ConfiguredObject<?> source, String attributeName, Object oldValue, Object newValue)
        {
            _source = source;
            _attributeName = attributeName;
            _oldValue = oldValue;
            _newValue = newValue;
            _eventType = eventType;
        }

        @Override
        public boolean equals(Object o)
        {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ChangeEvent that = (ChangeEvent) o;

            return (_source != null ? _source.equals(that._source) : that._source == null)
                    && (_attributeName != null ? _attributeName.equals(that._attributeName) : that._attributeName == null)
                    && (_oldValue != null ? _oldValue.equals(that._oldValue) : that._oldValue == null)
                    && (_newValue != null ? _newValue.equals(that._newValue) : that._newValue == null)
                    && _eventType == that._eventType;

        }

        @Override
        public String toString()
        {
            return "ChangeEvent{" +
                    "_source=" + _source +
                    ", _attributeName='" + _attributeName + '\'' +
                    ", _oldValue=" + _oldValue +
                    ", _newValue=" + _newValue +
                    ", _eventType=" + _eventType +
                    '}';
        }
    }
}
