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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.updater.Task;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectFactory;
import org.apache.qpid.server.util.ServerScopedRuntimeException;

public class GenericRecoverer
{
    private static final Logger LOGGER = LoggerFactory.getLogger(GenericRecoverer.class);

    private final ConfiguredObject<?> _root;

    public GenericRecoverer(ConfiguredObject<?> root)
    {
        _root = root;
    }

    public void recover(final List<ConfiguredObjectRecord> records, final boolean isNew)
    {
        _root.getTaskExecutor().run(new Task<Void, RuntimeException>()
        {
            @Override
            public Void execute()
            {
                performRecover(records, isNew);
                return null;
            }

            @Override
            public String getObject()
            {
                return _root.toString();
            }

            @Override
            public String getAction()
            {
                return "recover";
            }

            @Override
            public String getArguments()
            {
                return null;
            }
        });
    }

    private void performRecover(List<ConfiguredObjectRecord> records, final boolean isNew)
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Recovering the children of " + _root);
        }

        records = resolveDiscontinuity(records);
        resolveObjects(_root, records, isNew);
    }

    private List<ConfiguredObjectRecord> resolveDiscontinuity(final List<ConfiguredObjectRecord> records)
    {
        Collection<Class<? extends ConfiguredObject>> childTypesOfRoot = _root.getModel().getChildTypes(_root.getCategoryClass());
        List<ConfiguredObjectRecord> newRecords = new ArrayList<>(records.size());

        for (ConfiguredObjectRecord record : records)
        {
            if (record.getId().equals(_root.getId()))
            {
                // If the parent is already in the records, we skip it, this supports partial recovery
                // (required when restarting a virtualhost).  In the long term, when the objects take responsibility
                // for the recovery of immediate descendants only, this will disappear.
            }
            else if ((record.getParents() == null || record.getParents().size() == 0))
            {
                if (containsCategory(childTypesOfRoot, record.getType()))
                {
                    String parentOfRootCategory = _root.getCategoryClass().getSimpleName();
                    Map<String, UUID> rootParents = Collections.singletonMap(parentOfRootCategory, _root.getId());
                    newRecords.add(new ConfiguredObjectRecordImpl(record.getId(), record.getType(), record.getAttributes(), rootParents));
                }
                else
                {
                    throw new IllegalArgumentException("Recovered configured object record " + record
                                                       + " has no recorded parents and is not a valid child type"
                                                       + " [" + Arrays.toString(childTypesOfRoot.toArray()) + "]"
                                                       + " for the root " + _root);
                }
            }
            else
            {
                newRecords.add(record);
            }
        }

        return newRecords;
    }

    private boolean containsCategory(Collection<Class<? extends ConfiguredObject>> childCategories, String categorySimpleName)
    {
        for (Class<? extends ConfiguredObject> child : childCategories)
        {
            if (child.getSimpleName().equals(categorySimpleName))
            {
                return true;
            }
        }
        return false;
    }

    private void resolveObjects(ConfiguredObject<?> parentObject,
                                List<ConfiguredObjectRecord> records,
                                final boolean isNew)
    {
        ConfiguredObjectFactory factory = parentObject.getObjectFactory();
        Map<UUID, ConfiguredObject<?>> resolvedObjects = new HashMap<UUID, ConfiguredObject<?>>();
        resolvedObjects.put(parentObject.getId(), parentObject);

        Collection<ConfiguredObjectRecord> recordsWithUnresolvedParents = new ArrayList<ConfiguredObjectRecord>(records);
        Collection<UnresolvedConfiguredObject<? extends ConfiguredObject>> recordsWithUnresolvedDependencies =
                new ArrayList<UnresolvedConfiguredObject<? extends ConfiguredObject>>();

        boolean updatesMade;

        do
        {
            updatesMade = false;
            Iterator<ConfiguredObjectRecord> iter = recordsWithUnresolvedParents.iterator();
            while (iter.hasNext())
            {
                ConfiguredObjectRecord record = iter.next();
                Collection<ConfiguredObject<?>> parents = new ArrayList<ConfiguredObject<?>>();
                boolean foundParents = true;
                for (UUID parentId : record.getParents().values())
                {
                    if (!resolvedObjects.containsKey(parentId))
                    {
                        foundParents = false;
                        break;
                    }
                    else
                    {
                        parents.add(resolvedObjects.get(parentId));
                    }
                }
                if (parents.size() > 1)
                {
                    throw new IllegalStateException(String.format("Unexpected number of parents %d for record %s ", parents.size(), record));
                }
                if (foundParents)
                {
                    iter.remove();
                    ConfiguredObject<?>[] parentArray = parents.toArray(new ConfiguredObject<?>[parents.size()]);
                    UnresolvedConfiguredObject<? extends ConfiguredObject> recovered =  factory.recover(record, parentArray[0]);
                    Collection<ConfiguredObjectDependency<?>> dependencies = recovered.getUnresolvedDependencies();
                    if (dependencies.isEmpty())
                    {
                        updatesMade = true;
                        ConfiguredObject<?> resolved = recovered.resolve();
                        if(!isNew)
                        {
                            resolved.decryptSecrets();
                        }
                        resolvedObjects.put(resolved.getId(), resolved);
                    }
                    else
                    {
                        recordsWithUnresolvedDependencies.add(recovered);
                    }
                }

            }

            Iterator<UnresolvedConfiguredObject<? extends ConfiguredObject>> unresolvedIter = recordsWithUnresolvedDependencies.iterator();

            while(unresolvedIter.hasNext())
            {
                UnresolvedConfiguredObject<? extends ConfiguredObject> unresolvedObject = unresolvedIter.next();
                Collection<ConfiguredObjectDependency<?>> dependencies =
                        new ArrayList<ConfiguredObjectDependency<?>>(unresolvedObject.getUnresolvedDependencies());

                for(ConfiguredObjectDependency dependency : dependencies)
                {
                    if(dependency instanceof ConfiguredObjectIdDependency)
                    {
                        UUID id = ((ConfiguredObjectIdDependency)dependency).getId();
                        if(resolvedObjects.containsKey(id))
                        {
                            dependency.resolve(resolvedObjects.get(id));
                        }
                    }
                    else if(dependency instanceof ConfiguredObjectNameDependency)
                    {
                        ConfiguredObject<?> dependentObject = null;
                        ConfiguredObject<?> parent = unresolvedObject.getParent();
                        dependentObject = parent.findConfiguredObject(dependency.getCategoryClass(), ((ConfiguredObjectNameDependency)dependency).getName());
                        if(dependentObject != null)
                        {
                            dependency.resolve(dependentObject);
                        }
                    }
                    else
                    {
                        throw new ServerScopedRuntimeException("Unknown dependency type " + dependency.getClass().getSimpleName());
                    }
                }
                if(unresolvedObject.getUnresolvedDependencies().isEmpty())
                {
                    updatesMade = true;
                    unresolvedIter.remove();
                    ConfiguredObject<?> resolved = unresolvedObject.resolve();
                    resolvedObjects.put(resolved.getId(), resolved);
                }
            }

        } while(updatesMade && !(recordsWithUnresolvedDependencies.isEmpty() && recordsWithUnresolvedParents.isEmpty()));

        if(!recordsWithUnresolvedDependencies.isEmpty())
        {
            throw new IllegalArgumentException("Cannot resolve some objects: " + recordsWithUnresolvedDependencies);
        }
        if(!recordsWithUnresolvedParents.isEmpty())
        {
            throw new IllegalArgumentException("Cannot resolve object because their parents cannot be found" + recordsWithUnresolvedParents);
        }
    }

}
