/*
 *
 * 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;

import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.security.auth.Subject;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.CompositeStartupMessageLogger;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.MessageLogger;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.messages.BrokerMessages;
import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.ConfiguredObjectRecordConverter;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler;
import org.apache.qpid.server.store.preferences.NoopPreferenceStoreFactoryService;
import org.apache.qpid.server.store.preferences.PreferenceStore;
import org.apache.qpid.server.store.preferences.PreferenceStoreAttributes;
import org.apache.qpid.server.store.preferences.PreferenceStoreFactoryService;
import org.apache.qpid.server.util.ServerScopedRuntimeException;

public abstract class AbstractSystemConfig<X extends SystemConfig<X>>
        extends AbstractConfiguredObject<X> implements SystemConfig<X>, DynamicModel
{
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSystemConfig.class);

    private static final UUID SYSTEM_ID = new UUID(0l, 0l);
    private static final long SHUTDOWN_TIMEOUT = 30000l;

    private final Principal _systemPrincipal;

    private final EventLogger _eventLogger;

    private volatile DurableConfigurationStore _configurationStore;
    private Runnable _onContainerResolveTask;
    private Runnable _onContainerCloseTask;

    @ManagedAttributeField
    private boolean _managementMode;

    @ManagedAttributeField
    private int _managementModeHttpPortOverride;

    @ManagedAttributeField
    private boolean _managementModeQuiesceVirtualHosts;

    @ManagedAttributeField
    private String _managementModePassword;

    @ManagedAttributeField
    private String _initialConfigurationLocation;

    @ManagedAttributeField
    private boolean _startupLoggedToSystemOut;

    @ManagedAttributeField
    private PreferenceStoreAttributes _preferenceStoreAttributes;

    @ManagedAttributeField
    private String _defaultContainerType;

    private final Thread _shutdownHook = new Thread(new ShutdownService(), "QpidBrokerShutdownHook");

    public AbstractSystemConfig(final TaskExecutor taskExecutor,
                                final EventLogger eventLogger,
                                final Principal systemPrincipal,
                                final Map<String, Object> attributes)
    {
        super(parentsMap(),
              updateAttributes(attributes),
              taskExecutor, SystemConfigBootstrapModel.getInstance());
        _eventLogger = eventLogger;
        _systemPrincipal = systemPrincipal;
        getTaskExecutor().start();
    }

    private static Map<String, Object> updateAttributes(Map<String, Object> attributes)
    {
        attributes = new HashMap<>(attributes);
        attributes.put(ConfiguredObject.NAME, "System");
        attributes.put(ID, SYSTEM_ID);
        return attributes;
    }

    @Override
    protected void setState(final State desiredState)
    {
        throw new IllegalArgumentException("Cannot change the state of the SystemContext object");
    }

    @Override
    public EventLogger getEventLogger()
    {
        return _eventLogger;
    }

    @Override
    protected ListenableFuture<Void> beforeClose()
    {
        try
        {
            boolean removed = Runtime.getRuntime().removeShutdownHook(_shutdownHook);
            LOGGER.debug("Removed shutdown hook : {}", removed);
        }
        catch(IllegalStateException ise)
        {
            //ignore, means the JVM is already shutting down
        }

        return super.beforeClose();
    }

    @Override
    protected void onClose()
    {
        final TaskExecutor taskExecutor = getTaskExecutor();
        try
        {

            if (taskExecutor != null)
            {
                taskExecutor.stop();
            }

            if (_configurationStore != null)
            {
                _configurationStore.closeConfigurationStore();
            }

        }
        finally
        {
            if (taskExecutor != null)
            {
                taskExecutor.stopImmediately();
            }
        }

    }

    @Override
    public <C extends ConfiguredObject<C>> C getChild(Class<C> childClass)
    {
        Collection<C> children = getChildren(childClass);
        if(children == null || children.isEmpty())
        {
            return null;
        }
        else if(children.size() != 1)
        {
            throw new IllegalConfigurationException("More than one broker has been registered in a single context");
        }
        return children.iterator().next();
    }


    @Override
    protected void onOpen()
    {
        super.onOpen();

        Runtime.getRuntime().addShutdownHook(_shutdownHook);
        LOGGER.debug("Added shutdown hook");

        _configurationStore = createStoreObject();

        if (isManagementMode())
        {
            _configurationStore = new ManagementModeStoreHandler(_configurationStore, this);
        }

        _configurationStore.init(this);
        _configurationStore.upgradeStoreStructure();
    }

    @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
    protected ListenableFuture<Void> activate()
    {
        final EventLogger eventLogger = _eventLogger;
        final EventLogger startupLogger = initiateStartupLogging();


        try
        {
            final Container<?> container = initateStoreAndRecovery();

            container.setEventLogger(startupLogger);
            final SettableFuture<Void> returnVal = SettableFuture.create();
            Futures.addCallback(container.openAsync(), new FutureCallback()
                                {
                                    @Override
                                    public void onSuccess(final Object result)
                                    {
                                        State state = container.getState();
                                        if (state == State.ACTIVE)
                                        {
                                            startupLogger.message(BrokerMessages.READY());
                                            container.setEventLogger(eventLogger);
                                            returnVal.set(null);
                                        }
                                        else
                                        {
                                            returnVal.setException(new ServerScopedRuntimeException("Broker failed reach ACTIVE state (state is " + state + ")"));
                                        }
                                    }

                                    @Override
                                    public void onFailure(final Throwable t)
                                    {
                                        returnVal.setException(t);
                                    }
                                }, getTaskExecutor()
                               );

            return returnVal;
        }
        catch (IOException e)
        {
            throw new IllegalArgumentException(e);
        }


    }

    private Container<?> initateStoreAndRecovery() throws IOException
    {
        ConfiguredObjectRecord[] initialRecords = convertToConfigurationRecords(getInitialConfigurationLocation()
                                                                               );
        final DurableConfigurationStore store = getConfigurationStore();
        final List<ConfiguredObjectRecord> records = new ArrayList<>();

        boolean isNew = store.openConfigurationStore(new ConfiguredObjectRecordHandler()
        {
            @Override
            public void handle(final ConfiguredObjectRecord record)
            {
                records.add(record);
            }
        }, initialRecords);

        String containerTypeName = getDefaultContainerType();
        for(ConfiguredObjectRecord record : records)
        {
            if(record.getParents() != null && record.getParents().size() == 1 && getId().equals(record.getParents().get(SystemConfig.class.getSimpleName())))
            {
                containerTypeName = record.getType();
                break;
            }
        }
        QpidServiceLoader loader = new QpidServiceLoader();
        final ContainerType<?> containerType = loader.getInstancesByType(ContainerType.class).get(containerTypeName);

        if(containerType != null)
        {
            updateModel(containerType.getModel());
            containerType.getRecoverer(this).upgradeAndRecover(records);

        }
        else
        {
            throw new IllegalConfigurationException("Unknown container type '" + containerTypeName + "'");
        }

        final Class categoryClass = containerType.getCategoryClass();
        return (Container<?>) getChild(categoryClass);
    }


    @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.QUIESCED)
    protected ListenableFuture<Void> startQuiesced()
    {
        final EventLogger startupLogger = initiateStartupLogging();

        try
        {
            final Container<?> container = initateStoreAndRecovery();

            container.setEventLogger(startupLogger);
            return Futures.immediateFuture(null);
        }
        catch (IOException e)
        {
            throw new IllegalArgumentException(e);
        }


    }

    private EventLogger initiateStartupLogging()
    {
        final EventLogger eventLogger = _eventLogger;

        final EventLogger startupLogger;
        if (isStartupLoggedToSystemOut())
        {
            //Create the composite (logging+SystemOut MessageLogger to be used during startup
            MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), eventLogger.getMessageLogger()};

            CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers);
            startupLogger = new EventLogger(startupMessageLogger);
        }
        else
        {
            startupLogger = eventLogger;
        }
        return startupLogger;
    }


    @Override
    protected final boolean rethrowRuntimeExceptionsOnOpen()
    {
        return true;
    }

    protected abstract DurableConfigurationStore createStoreObject();

    @Override
    public DurableConfigurationStore getConfigurationStore()
    {
        return _configurationStore;
    }

    private ConfiguredObjectRecord[] convertToConfigurationRecords(final String initialConfigurationLocation) throws IOException
    {
        ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(getModel());

        Reader reader;

        try
        {
            URL url = new URL(initialConfigurationLocation);
            reader = new InputStreamReader(url.openStream());
        }
        catch (MalformedURLException e)
        {
            reader = new FileReader(initialConfigurationLocation);
        }

        try
        {
            Collection<ConfiguredObjectRecord> records =
                    converter.readFromJson(null, this, reader);
            return records.toArray(new ConfiguredObjectRecord[records.size()]);
        }
        finally
        {
            reader.close();
        }


    }

    @Override
    public String getDefaultContainerType()
    {
        return _defaultContainerType;
    }

    @Override
    public boolean isManagementMode()
    {
        return _managementMode;
    }

    @Override
    public int getManagementModeHttpPortOverride()
    {
        return _managementModeHttpPortOverride;
    }

    @Override
    public boolean isManagementModeQuiesceVirtualHosts()
    {
        return _managementModeQuiesceVirtualHosts;
    }

    @Override
    public String getManagementModePassword()
    {
        return _managementModePassword;
    }

    @Override
    public String getInitialConfigurationLocation()
    {
        return _initialConfigurationLocation;
    }

    @Override
    public boolean isStartupLoggedToSystemOut()
    {
        return _startupLoggedToSystemOut;
    }


    @Override
    public PreferenceStoreAttributes getPreferenceStoreAttributes()
    {
        return _preferenceStoreAttributes;
    }

    @Override
    public PreferenceStore createPreferenceStore()
    {
        PreferenceStoreAttributes preferenceStoreAttributes = getPreferenceStoreAttributes();
        final Map<String, PreferenceStoreFactoryService> preferenceStoreFactories = new QpidServiceLoader().getInstancesByType(PreferenceStoreFactoryService.class);
        String preferenceStoreType;
        Map<String, Object> attributes;
        if (preferenceStoreAttributes == null)
        {
            preferenceStoreType = NoopPreferenceStoreFactoryService.TYPE;
            attributes = Collections.emptyMap();
        }
        else
        {
            preferenceStoreType = preferenceStoreAttributes.getType();
            attributes = preferenceStoreAttributes.getAttributes();
        }
        final PreferenceStoreFactoryService preferenceStoreFactory = preferenceStoreFactories.get(preferenceStoreType);
        return preferenceStoreFactory.createInstance(this, attributes);
    }

    protected final Principal getSystemPrincipal()
    {
        return _systemPrincipal;
    }

    public Runnable getOnContainerResolveTask()
    {
        return _onContainerResolveTask;
    }

    @Override
    public void setOnContainerResolveTask(final Runnable onContainerResolveTask)
    {
        _onContainerResolveTask = onContainerResolveTask;
    }

    public Runnable getOnContainerCloseTask()
    {
        return _onContainerCloseTask;
    }

    public void setOnContainerCloseTask(final Runnable onContainerCloseTask)
    {
        _onContainerCloseTask = onContainerCloseTask;
    }

    private class ShutdownService implements Runnable
    {
        public void run()
        {
            Subject.doAs(getSystemTaskSubject("Shutdown"),
                         new PrivilegedAction<Object>()
                         {
                             @Override
                             public Object run()
                             {
                                 LOGGER.debug("Shutdown hook initiating close");
                                 ListenableFuture<Void> closeResult = closeAsync();
                                 try
                                 {
                                     closeResult.get(SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
                                 }
                                 catch (InterruptedException | ExecutionException  | TimeoutException e)
                                 {
                                     LOGGER.warn("Attempting to cleanly shutdown took too long, exiting immediately", e);
                                 }
                                 return null;
                             }
                         });
        }
    }

}
