//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.util.component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/**
 * A ContainerLifeCycle is an {@link LifeCycle} implementation for a collection of contained beans.
 * <p>
 * Beans can be added to the ContainerLifeCycle either as managed beans or as unmanaged beans.
 * A managed bean is started, stopped and destroyed with the aggregate.
 * An unmanaged bean is associated with the aggregate for the purposes of {@link #dump()}, but its
 * lifecycle must be managed externally.
 * <p>
 * When a {@link LifeCycle} bean is added without a managed state being specified the state is
 * determined heuristically:
 * <ul>
 *   <li>If the added bean is running, it will be added as an unmanaged bean.</li>
 *   <li>If the added bean is !running and the container is !running, it will be added as an AUTO bean (see below).</li>
 *   <li>If the added bean is !running and the container is starting, it will be added as a managed bean
 *   and will be started (this handles the frequent case of new beans added during calls to doStart).</li>
 *   <li>If the added bean is !running and the container is started, it will be added as an unmanaged bean.</li>
 * </ul>
 * When the container is started, then all contained managed beans will also be started.
 * Any contained AUTO beans will be check for their status and if already started will be switched unmanaged beans,
 * else they will be started and switched to managed beans.
 * Beans added after a container is started are not started and their state needs to be explicitly managed.
 * <p>
 * When stopping the container, a contained bean will be stopped by this aggregate only if it
 * is started by this aggregate.
 * <p>
 * The methods {@link #addBean(Object, boolean)}, {@link #manage(Object)} and {@link #unmanage(Object)} can be used to
 * explicitly control the life cycle relationship.
 * <p>
 * If adding a bean that is shared between multiple {@link ContainerLifeCycle} instances, then it should be started
 * before being added, so it is unmanaged, or the API must be used to explicitly set it as unmanaged.
 * <p>
 * This class also provides utility methods to dump deep structures of objects.
 * In the dump, the following symbols are used to indicate the type of contained object:
 * <pre>
 * SomeContainerLifeCycleInstance
 *   +- contained POJO instance
 *   += contained MANAGED object, started and stopped with this instance
 *   +~ referenced UNMANAGED object, with separate lifecycle
 *   +? referenced AUTO object that could become MANAGED or UNMANAGED.
 * </pre>
 */
@ManagedObject("Implementation of Container and LifeCycle")
public class ContainerLifeCycle extends AbstractLifeCycle implements Container, Destroyable, Dumpable
{
    private static final Logger LOG = Log.getLogger(ContainerLifeCycle.class);
    private final List<Bean> _beans = new CopyOnWriteArrayList<>();
    private final List<Container.Listener> _listeners = new CopyOnWriteArrayList<>();
    private boolean _doStarted;
    private boolean _destroyed;

    /**
     * Starts the managed lifecycle beans in the order they were added.
     */
    @Override
    protected void doStart() throws Exception
    {
        if (_destroyed)
            throw new IllegalStateException("Destroyed container cannot be restarted");

        // indicate that we are started, so that addBean will start other beans added.
        _doStarted = true;

        // start our managed and auto beans
        for (Bean b : _beans)
        {
            if (b._bean instanceof LifeCycle)
            {
                LifeCycle l = (LifeCycle)b._bean;
                switch(b._managed)
                {
                    case MANAGED:
                        if (!l.isRunning())
                            start(l);
                        break;
                    case AUTO:
                        if (l.isRunning())
                            unmanage(b);
                        else
                        {
                            manage(b);
                            start(l);
                        }
                        break;
                }
            }
        }

        super.doStart();
    }

    /**
     * Starts the given lifecycle.
     *
     * @param l the lifecycle to start
     * @throws Exception if unable to start lifecycle
     */
    protected void start(LifeCycle l) throws Exception
    {
        l.start();
    }
    
    /**
     * Stops the given lifecycle.
     *
     * @param l the lifecycle to stop
     * @throws Exception if unable to stop the lifecycle
     */
    protected void stop(LifeCycle l) throws Exception
    {
        l.stop();
    }

    /**
     * Stops the managed lifecycle beans in the reverse order they were added.
     */
    @Override
    protected void doStop() throws Exception
    {
        _doStarted = false;
        super.doStop();
        List<Bean> reverse = new ArrayList<>(_beans);
        Collections.reverse(reverse);
        for (Bean b : reverse)
        {
            if (b._managed==Managed.MANAGED && b._bean instanceof LifeCycle)
            {
                LifeCycle l = (LifeCycle)b._bean;
                stop(l);
            }
        }
    }

    /**
     * Destroys the managed Destroyable beans in the reverse order they were added.
     */
    @Override
    public void destroy()
    {
        _destroyed = true;
        List<Bean> reverse = new ArrayList<>(_beans);
        Collections.reverse(reverse);
        for (Bean b : reverse)
        {
            if (b._bean instanceof Destroyable && (b._managed==Managed.MANAGED || b._managed==Managed.POJO))
            {
                Destroyable d = (Destroyable)b._bean;
                d.destroy();
            }
        }
        _beans.clear();
    }

    /**
     * @param bean the bean to test
     * @return whether this aggregate contains the bean
     */
    public boolean contains(Object bean)
    {
        for (Bean b : _beans)
            if (b._bean == bean)
                return true;
        return false;
    }

    /**
     * @param bean the bean to test
     * @return whether this aggregate contains and manages the bean
     */
    public boolean isManaged(Object bean)
    {
        for (Bean b : _beans)
            if (b._bean == bean)
                return b.isManaged();
        return false;
    }

    /**
     * Adds the given bean, detecting whether to manage it or not.
     * If the bean is a {@link LifeCycle}, then it will be managed if it is not
     * already started and not managed if it is already started.
     * The {@link #addBean(Object, boolean)}
     * method should be used if this is not correct, or the {@link #manage(Object)} and {@link #unmanage(Object)}
     * methods may be used after an add to change the status.
     *
     * @param o the bean object to add
     * @return true if the bean was added, false if it was already present
     */
    @Override
    public boolean addBean(Object o)
    {
        if (o instanceof LifeCycle)
        {
            LifeCycle l = (LifeCycle)o;
            return addBean(o,l.isRunning()?Managed.UNMANAGED:Managed.AUTO);
        }

        return addBean(o,Managed.POJO);
    }

    /**
     * Adds the given bean, explicitly managing it or not.
     *
     * @param o       The bean object to add
     * @param managed whether to managed the lifecycle of the bean
     * @return true if the bean was added, false if it was already present
     */
    public boolean addBean(Object o, boolean managed)
    {
        if (o instanceof LifeCycle)
            return addBean(o,managed?Managed.MANAGED:Managed.UNMANAGED);
        return addBean(o,managed?Managed.POJO:Managed.UNMANAGED);
    }

    public boolean addBean(Object o, Managed managed)
    {
        if (o==null || contains(o))
            return false;

        Bean new_bean = new Bean(o);

        // if the bean is a Listener
        if (o instanceof Container.Listener)
            addEventListener((Container.Listener)o);

        // Add the bean
        _beans.add(new_bean);

        // Tell existing listeners about the new bean
        for (Container.Listener l:_listeners)
            l.beanAdded(this,o);

        try
        {
            switch (managed)
            {
                case UNMANAGED:
                    unmanage(new_bean);
                    break;

                case MANAGED:
                    manage(new_bean);

                    if (isStarting() && _doStarted)
                    {
                        LifeCycle l = (LifeCycle)o;
                        if (!l.isRunning())
                            start(l);
                    }
                    break;

                case AUTO:
                    if (o instanceof LifeCycle)
                    {
                        LifeCycle l = (LifeCycle)o;
                        if (isStarting())
                        {
                            if (l.isRunning())
                                unmanage(new_bean);
                            else if (_doStarted)
                            {
                                manage(new_bean);
                                start(l);
                            }
                            else
                                new_bean._managed=Managed.AUTO;      
                        }
                        else if (isStarted())
                            unmanage(new_bean);
                        else
                            new_bean._managed=Managed.AUTO;
                    }
                    else
                        new_bean._managed=Managed.POJO;
                    break;

                case POJO:
                    new_bean._managed=Managed.POJO;
            }
        }
        catch (RuntimeException | Error e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }

        if (LOG.isDebugEnabled())
            LOG.debug("{} added {}",this,new_bean);

        return true;
    }

    /**
     * Adds a managed lifecycle.
     * <p>This is a convenience method that uses addBean(lifecycle,true)
     * and then ensures that the added bean is started iff this container
     * is running.  Exception from nested calls to start are caught and 
     * wrapped as RuntimeExceptions
     * @param lifecycle the managed lifecycle to add
     */
    public void addManaged(LifeCycle lifecycle)
    {
        addBean(lifecycle,true);
        try
        {
            if (isRunning() && !lifecycle.isRunning())
                start(lifecycle);
        }
        catch (RuntimeException | Error e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void addEventListener(Container.Listener listener)
    {
        if (_listeners.contains(listener))
            return;
        
        _listeners.add(listener);

        // tell it about existing beans
        for (Bean b:_beans)
        {
            listener.beanAdded(this,b._bean);

            // handle inheritance
            if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
            {
                if (b._bean instanceof ContainerLifeCycle)
                     ((ContainerLifeCycle)b._bean).addBean(listener, false);
                 else
                     ((Container)b._bean).addBean(listener);
            }
        }
    }

    /**
     * Manages a bean already contained by this aggregate, so that it is started/stopped/destroyed with this
     * aggregate.
     *
     * @param bean The bean to manage (must already have been added).
     */
    public void manage(Object bean)
    {
        for (Bean b : _beans)
        {
            if (b._bean == bean)
            {
                manage(b);
                return;
            }
        }
        throw new IllegalArgumentException("Unknown bean " + bean);
    }

    private void manage(Bean bean)
    {
        if (bean._managed!=Managed.MANAGED)
        {
            bean._managed=Managed.MANAGED;

            if (bean._bean instanceof Container)
            {
                for (Container.Listener l:_listeners)
                {
                    if (l instanceof InheritedListener)
                    {
                        if (bean._bean instanceof ContainerLifeCycle)
                            ((ContainerLifeCycle)bean._bean).addBean(l,false);
                        else
                            ((Container)bean._bean).addBean(l);
                    }
                }
            }

            if (bean._bean instanceof AbstractLifeCycle)
            {
                ((AbstractLifeCycle)bean._bean).setStopTimeout(getStopTimeout());
            }
        }
    }

    /**
     * Unmanages a bean already contained by this aggregate, so that it is not started/stopped/destroyed with this
     * aggregate.
     *
     * @param bean The bean to unmanage (must already have been added).
     */
    public void unmanage(Object bean)
    {
        for (Bean b : _beans)
        {
            if (b._bean == bean)
            {
                unmanage(b);
                return;
            }
        }
        throw new IllegalArgumentException("Unknown bean " + bean);
    }

    private void unmanage(Bean bean)
    {
        if (bean._managed!=Managed.UNMANAGED)
        {
            if (bean._managed==Managed.MANAGED && bean._bean instanceof Container)
            {
                for (Container.Listener l:_listeners)
                {
                    if (l instanceof InheritedListener)
                        ((Container)bean._bean).removeBean(l);
                }
            }
            bean._managed=Managed.UNMANAGED;
        }
    }

    @Override
    public Collection<Object> getBeans()
    {
        return getBeans(Object.class);
    }

    public void setBeans(Collection<Object> beans)
    {
        for (Object bean : beans)
            addBean(bean);
    }

    @Override
    public <T> Collection<T> getBeans(Class<T> clazz)
    {
        ArrayList<T> beans = new ArrayList<>();
        for (Bean b : _beans)
        {
            if (clazz.isInstance(b._bean))
                beans.add(clazz.cast(b._bean));
        }
        return beans;
    }

    @Override
    public <T> T getBean(Class<T> clazz)
    {
        for (Bean b : _beans)
        {
            if (clazz.isInstance(b._bean))
                return clazz.cast(b._bean);
        }
        return null;
    }

    /**
     * Removes all bean
     */
    public void removeBeans()
    {
        ArrayList<Bean> beans= new ArrayList<>(_beans);
        for (Bean b : beans)
            remove(b);
    }

    private Bean getBean(Object o)
    {
        for (Bean b : _beans)
        {
            if (b._bean == o)
                return b;
        }
        return null;
    }

    @Override
    public boolean removeBean(Object o)
    {
        Bean b=getBean(o);
        return b!=null && remove(b);
    }

    private boolean remove(Bean bean)
    {
        if (_beans.remove(bean))
        {
            boolean wasManaged = bean.isManaged();
            
            unmanage(bean);

            for (Container.Listener l:_listeners)
                l.beanRemoved(this,bean._bean);

            if (bean._bean instanceof Container.Listener)
                removeEventListener((Container.Listener)bean._bean);

            // stop managed beans
            if (wasManaged && bean._bean instanceof LifeCycle)
            {
                try
                {
                    stop((LifeCycle)bean._bean);
                }
                catch(RuntimeException | Error e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new RuntimeException(e);
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public void removeEventListener(Container.Listener listener)
    {
        if (_listeners.remove(listener))
        {
            // remove existing beans
            for (Bean b:_beans)
            {
                listener.beanRemoved(this,b._bean);

                if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
                    ((Container)b._bean).removeBean(listener);
            }
        }
    }

    @Override
    public void setStopTimeout(long stopTimeout)
    {
        super.setStopTimeout(stopTimeout);
        for (Bean bean : _beans)
        {
            if (bean.isManaged() && bean._bean instanceof AbstractLifeCycle)
                ((AbstractLifeCycle)bean._bean).setStopTimeout(stopTimeout);
        }
    }

    /**
     * Dumps to {@link System#err}.
     * @see #dump()
     */
    @ManagedOperation("Dump the object to stderr")
    public void dumpStdErr()
    {
        try
        {
            dump(System.err, "");
        }
        catch (IOException e)
        {
            LOG.warn(e);
        }
    }

    @Override
    @ManagedOperation("Dump the object to a string")
    public String dump()
    {
        return dump(this);
    }

    public static String dump(Dumpable dumpable)
    {
        StringBuilder b = new StringBuilder();
        try
        {
            dumpable.dump(b, "");
        }
        catch (IOException e)
        {
            LOG.warn(e);
        }
        return b.toString();
    }

    public void dump(Appendable out) throws IOException
    {
        dump(out, "");
    }

    protected void dumpThis(Appendable out) throws IOException
    {
        out.append(String.valueOf(this)).append(" - ").append(getState()).append("\n");
    }

    public static void dumpObject(Appendable out, Object o) throws IOException
    {
        try
        {
            if (o instanceof LifeCycle)
                out.append(String.valueOf(o)).append(" - ").append((AbstractLifeCycle.getState((LifeCycle)o))).append("\n");
            else
                out.append(String.valueOf(o)).append("\n");
        }
        catch (Throwable th)
        {
            out.append(" => ").append(th.toString()).append('\n');
        }
    }

    @Override
    public void dump(Appendable out, String indent) throws IOException
    {
        dumpBeans(out,indent);
    }

    protected void dumpBeans(Appendable out, String indent, Collection<?>... collections) throws IOException
    {
        dumpThis(out);
        int size = _beans.size();
        for (Collection<?> c : collections)
            size += c.size();
        if (size == 0)
            return;
        int i = 0;
        for (Bean b : _beans)
        {
            i++;

            switch(b._managed)
            {
                case POJO:
                    out.append(indent).append(" +- ");
                    if (b._bean instanceof Dumpable)
                        ((Dumpable)b._bean).dump(out, indent + (i == size ? "    " : " |  "));
                    else
                        dumpObject(out, b._bean);
                    break;

                case MANAGED:
                    out.append(indent).append(" += ");
                    if (b._bean instanceof Dumpable)
                        ((Dumpable)b._bean).dump(out, indent + (i == size ? "    " : " |  "));
                    else
                        dumpObject(out, b._bean);
                    break;

                case UNMANAGED:
                    out.append(indent).append(" +~ ");
                    dumpObject(out, b._bean);
                    break;

                case AUTO:
                    out.append(indent).append(" +? ");
                    if (b._bean instanceof Dumpable)
                        ((Dumpable)b._bean).dump(out, indent + (i == size ? "    " : " |  "));
                    else
                        dumpObject(out, b._bean);
                    break;

            }
        }

        if (i<size)
            out.append(indent).append(" |\n");

        for (Collection<?> c : collections)
        {
            for (Object o : c)
            {
                i++;
                out.append(indent).append(" +> ");

                if (o instanceof Dumpable)
                    ((Dumpable)o).dump(out, indent + (i == size ? "    " : " |  "));
                else
                    dumpObject(out, o);
            }
        }
    }

    public static void dump(Appendable out, String indent, Collection<?>... collections) throws IOException
    {
        if (collections.length == 0)
            return;
        int size = 0;
        for (Collection<?> c : collections)
            size += c.size();
        if (size == 0)
            return;

        int i = 0;
        for (Collection<?> c : collections)
        {
            for (Object o : c)
            {
                i++;
                out.append(indent).append(" +- ");

                if (o instanceof Dumpable)
                    ((Dumpable)o).dump(out, indent + (i == size ? "    " : " |  "));
                else
                    dumpObject(out, o);
            }
        }
    }

    enum Managed { POJO, MANAGED, UNMANAGED, AUTO }

    private static class Bean
    {
        private final Object _bean;
        private volatile Managed _managed = Managed.POJO;

        private Bean(Object b)
        {
            if (b==null)
                throw new NullPointerException();
            _bean = b;
        }

        public boolean isManaged()
        {
            return _managed==Managed.MANAGED;
        }

        @Override
        public String toString()
        {
            return String.format("{%s,%s}", _bean, _managed);
        }
    }

    public void updateBean(Object oldBean, final Object newBean)
    {
        if (newBean!=oldBean)
        {
            if (oldBean!=null)
                removeBean(oldBean);
            if (newBean!=null)
                addBean(newBean);
        }
    }
    
    public void updateBean(Object oldBean, final Object newBean, boolean managed)
    {
        if (newBean!=oldBean)
        {
            if (oldBean!=null)
                removeBean(oldBean);
            if (newBean!=null)
                addBean(newBean,managed);
        }
    }

    public void updateBeans(Object[] oldBeans, final Object[] newBeans)
    {
        // remove oldChildren not in newChildren
        if (oldBeans!=null)
        {
            loop: for (Object o:oldBeans)
            {
                if (newBeans!=null)
                {
                    for (Object n:newBeans)
                        if (o==n)
                            continue loop;
                }
                removeBean(o);
            }
        }

        // add new beans not in old
        if (newBeans!=null)
        {
            loop: for (Object n:newBeans)
            {
                if (oldBeans!=null)
                {
                    for (Object o:oldBeans)
                        if (o==n)
                            continue loop;
                }
                addBean(n);
            }
        }
    }
}
