/*
 *
 * 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.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectJacksonModule;
import org.apache.qpid.server.model.ContainerType;
import org.apache.qpid.server.model.DynamicModel;
import org.apache.qpid.server.model.Model;
import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler;

public class JsonFileConfigStore extends AbstractJsonFileStore implements DurableConfigurationStore
{
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonFileConfigStore.class);

    private static final Comparator<Class<? extends ConfiguredObject>> CATEGORY_CLASS_COMPARATOR =
            new Comparator<Class<? extends ConfiguredObject>>()
            {
                @Override
                public int compare(final Class<? extends ConfiguredObject> left,
                                   final Class<? extends ConfiguredObject> right)
                {
                    return left.getSimpleName().compareTo(right.getSimpleName());
                }
            };
    private static final Comparator<ConfiguredObjectRecord> CONFIGURED_OBJECT_RECORD_COMPARATOR =
            new Comparator<ConfiguredObjectRecord>()
            {
                @Override
                public int compare(final ConfiguredObjectRecord left, final ConfiguredObjectRecord right)
                {
                    String leftName = (String) left.getAttributes().get(ConfiguredObject.NAME);
                    String rightName = (String) right.getAttributes().get(ConfiguredObject.NAME);
                    return leftName.compareTo(rightName);
                }
            };

    private final Map<UUID, ConfiguredObjectRecord> _objectsById = new HashMap<UUID, ConfiguredObjectRecord>();
    private final Map<String, List<UUID>> _idsByType = new HashMap<String, List<UUID>>();
    private volatile Class<? extends ConfiguredObject> _rootClass;
    private final ObjectMapper _objectMapper;
    private volatile Map<String,Class<? extends ConfiguredObject>> _classNameMapping;

    private ConfiguredObject<?> _parent;

    private enum State { CLOSED, CONFIGURED, OPEN };
    private State _state = State.CLOSED;
    private final Object _lock = new Object();

    public JsonFileConfigStore(Class<? extends ConfiguredObject> rootClass)
    {
        super();
        _objectMapper = ConfiguredObjectJacksonModule.newObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
        _rootClass = rootClass;
    }

    @Override
    public void upgradeStoreStructure() throws StoreException
    {
        // No-op for Json
    }

    @Override
    public void init(ConfiguredObject<?> parent)
    {
        assertState(State.CLOSED);
        _parent = parent;
        _classNameMapping = generateClassNameMap(_parent.getModel(), _rootClass);

        FileBasedSettings fileBasedSettings = (FileBasedSettings) _parent;
        setup(parent.getName(),
              fileBasedSettings.getStorePath(),
              parent.getContextValue(String.class, BrokerProperties.POSIX_FILE_PERMISSIONS),
              Collections.emptyMap());
        changeState(State.CLOSED, State.CONFIGURED);

    }

    @Override
    public boolean openConfigurationStore(ConfiguredObjectRecordHandler handler,
                                          final ConfiguredObjectRecord... initialRecords)
    {
        changeState(State.CONFIGURED, State.OPEN);
        boolean isNew = load(initialRecords);
        List<ConfiguredObjectRecord> records = new ArrayList<ConfiguredObjectRecord>(_objectsById.values());
        for(ConfiguredObjectRecord record : records)
        {
            handler.handle(record);
        }
        return isNew;
    }

    @Override
    public void reload(ConfiguredObjectRecordHandler handler)
    {
        assertState(State.OPEN);
        _idsByType.clear();
        _objectsById.clear();
        load();
        List<ConfiguredObjectRecord> records = new ArrayList<ConfiguredObjectRecord>(_objectsById.values());
        for(ConfiguredObjectRecord record : records)
        {
            handler.handle(record);
        }
    }


    protected boolean load(final ConfiguredObjectRecord... initialRecords)
    {
        final File configFile = getConfigFile();
        try
        {
            LOGGER.debug("Loading file {}", configFile.getCanonicalPath());

            boolean updated = false;
            Collection<ConfiguredObjectRecord> records = Collections.emptyList();
            ConfiguredObjectRecordConverter configuredObjectRecordConverter =
                    new ConfiguredObjectRecordConverter(_parent.getModel());

            records = configuredObjectRecordConverter.readFromJson(_rootClass, _parent, new FileReader(configFile));

            if(_rootClass == null)
            {
                _rootClass = configuredObjectRecordConverter.getRootClass();
                _classNameMapping = generateClassNameMap(configuredObjectRecordConverter.getModel(), _rootClass);
            }

            if(records.isEmpty())
            {
                LOGGER.debug("File contains no records - using initial configuration");
                records = Arrays.asList(initialRecords);
                updated = true;
                if (_rootClass == null)
                {
                    String containerTypeName = ((DynamicModel) _parent).getDefaultContainerType();
                    ConfiguredObjectRecord rootRecord = null;
                    for(ConfiguredObjectRecord record : records)
                    {
                        if(record.getParents() == null || record.getParents().isEmpty())
                        {
                            rootRecord = record;
                            break;
                        }
                    }
                    if (rootRecord != null && rootRecord.getAttributes().get(ConfiguredObject.TYPE) instanceof String)
                    {
                        containerTypeName = rootRecord.getAttributes().get(ConfiguredObject.TYPE).toString();
                    }

                    QpidServiceLoader loader = new QpidServiceLoader();
                    final ContainerType<?> containerType =
                            loader.getInstancesByType(ContainerType.class).get(containerTypeName);

                    if (containerType != null)
                    {
                        _rootClass = containerType.getCategoryClass();
                        _classNameMapping = generateClassNameMap(containerType.getModel(), containerType.getCategoryClass());
                    }

                }
            }

            for(ConfiguredObjectRecord record : records)
            {
                LOGGER.debug("Loading record (Category: {} \t Name: {} \t ID: {}", record.getType(), record.getAttributes().get("name"), record.getId());
                _objectsById.put(record.getId(), record);
                List<UUID> idsForType = _idsByType.get(record.getType());
                if (idsForType == null)
                {
                    idsForType = new ArrayList<>();
                    _idsByType.put(record.getType(), idsForType);
                }
                if(idsForType.contains(record.getId()))
                {
                    throw new IllegalArgumentException("Duplicate id for record " + record);
                }
                idsForType.add(record.getId());
            }
            if(updated)
            {
                save();
            }
            return updated;
        }
        catch (IOException e)
        {
            throw new StoreException("Cannot construct configuration from the configuration file " + configFile, e);
        }
    }

    @Override
    public synchronized void create(ConfiguredObjectRecord record) throws StoreException
    {
        assertState(State.OPEN);
        if(_objectsById.containsKey(record.getId()))
        {
            throw new StoreException("Object with id " + record.getId() + " already exists");
        }
        else if(!_classNameMapping.containsKey(record.getType()))
        {
            throw new StoreException("Cannot create object of unknown type " + record.getType());
        }
        else if(record.getAttributes() == null || !(record.getAttributes().get(ConfiguredObject.NAME) instanceof String))
        {
            throw new StoreException("The record " + record.getId()
                                     + " of type " + record.getType()
                                     + " does not have an attribute '"
                                     + ConfiguredObject.NAME
                                     + "' of type String");
        }
        else
        {
            record = new ConfiguredObjectRecordImpl(record);
            _objectsById.put(record.getId(), record);
            List<UUID> idsForType = _idsByType.get(record.getType());
            if(idsForType == null)
            {
                idsForType = new ArrayList<UUID>();
                _idsByType.put(record.getType(), idsForType);
            }

            if (_rootClass.getSimpleName().equals(record.getType()) && idsForType.size() > 0)
            {
                throw new IllegalStateException("Only a single root entry of type " + _rootClass.getSimpleName() + " can exist in the store.");
            }
            if(idsForType.contains(record.getId()))
            {
                throw new IllegalArgumentException("Duplicate id for record " + record);
            }

            idsForType.add(record.getId());

            save();
        }
    }

    private UUID getRootId()
    {
        List<UUID> ids = _idsByType.get(_rootClass.getSimpleName());
        if (ids == null)
        {
            return null;
        }
        if (ids.size() == 0)
        {
            return null;
        }
        return ids.get(0);
    }

    private void save()
    {
        UUID rootId = getRootId();
        final Map<String, Object> data;
        if (rootId == null)
        {
            data = Collections.emptyMap();
        }
        else
        {
            data = build(_rootClass, rootId, createChildMap());
        }

        save(data);
    }

    private HashMap<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> createChildMap()
    {
        Model model = _parent.getModel();
        HashMap<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> map = new HashMap<>();

        for(ConfiguredObjectRecord record : _objectsById.values())
        {
            int parentCount = record.getParents().size();
            if (parentCount == 0)
            {
                continue;
            }
            Collection<Class<? extends ConfiguredObject>> parentTypes =
                    model.getParentTypes(_classNameMapping.get(record.getType()));
            if (parentTypes != null && !parentTypes.isEmpty())
            {

                final Class<? extends ConfiguredObject> primaryParentCategory =
                        parentTypes.iterator().next();

                String parentCategoryName = primaryParentCategory.getSimpleName();

                UUID parentId = record.getParents().get(parentCategoryName);

                if (parentId != null)
                {
                    Map<String, SortedSet<ConfiguredObjectRecord>> childMap = map.get(parentId);
                    if (childMap == null)
                    {
                        childMap = new TreeMap<>();
                        map.put(parentId, childMap);
                    }
                    SortedSet<ConfiguredObjectRecord> children = childMap.get(record.getType());
                    if (children == null)
                    {
                        children = new TreeSet<>(CONFIGURED_OBJECT_RECORD_COMPARATOR);
                        childMap.put(record.getType(), children);
                    }
                    children.add(record);
                }
            }
        }
        return map;
    }

    private Map<String, Object> build(final Class<? extends ConfiguredObject> type, final UUID id,
                                      Map<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> childMap)
    {
        ConfiguredObjectRecord record = _objectsById.get(id);
        Map<String,Object> map = new LinkedHashMap<String, Object>();

        Collection<Class<? extends ConfiguredObject>> parentTypes = _parent.getModel().getParentTypes(type);
        if(parentTypes.size() > 1)
        {
            Iterator<Class<? extends ConfiguredObject>> iter = parentTypes.iterator();
            // skip the first parent, which is given by structure
            iter.next();
            // for all other parents add a fake attribute with name being the parent type in lower case, and the value
            // being the parents id
            while(iter.hasNext())
            {
                String parentType = iter.next().getSimpleName();
                map.put(parentType.toLowerCase(), record.getParents().get(parentType));
            }
        }

        map.put("id", id);
        map.putAll(record.getAttributes());

        List<Class<? extends ConfiguredObject>> childClasses =
                new ArrayList<Class<? extends ConfiguredObject>>(_parent.getModel().getChildTypes(type));

        Collections.sort(childClasses, CATEGORY_CLASS_COMPARATOR);

        final Map<String, SortedSet<ConfiguredObjectRecord>> allChildren = childMap.get(id);
        if(allChildren != null && !allChildren.isEmpty())
        {
            for(Map.Entry<String, SortedSet<ConfiguredObjectRecord>> entry : allChildren.entrySet())
            {
                String singularName = entry.getKey().toLowerCase();
                String attrName = singularName + (singularName.endsWith("s") ? "es" : "s");
                final SortedSet<ConfiguredObjectRecord> sortedChildren = entry.getValue();
                List<Map<String,Object>> entities = new ArrayList<Map<String, Object>>();

                for(ConfiguredObjectRecord childRecord : sortedChildren)
                {
                    entities.add(build(_classNameMapping.get(entry.getKey()), childRecord.getId(), childMap));
                }

                if(!entities.isEmpty())
                {
                    map.put(attrName,entities);
                }
            }
        }

        return map;
    }

    @Override
    public synchronized UUID[] remove(final ConfiguredObjectRecord... objects) throws StoreException
    {
        assertState(State.OPEN);

        if (objects.length == 0)
        {
            return new UUID[0];
        }

        List<UUID> removedIds = new ArrayList<UUID>();
        for(ConfiguredObjectRecord requestedRecord : objects)
        {
            ConfiguredObjectRecord record = _objectsById.remove(requestedRecord.getId());
            if(record != null)
            {
                removedIds.add(record.getId());
                _idsByType.get(record.getType()).remove(record.getId());
            }
        }
        save();
        return removedIds.toArray(new UUID[removedIds.size()]);
    }


    @Override
    public synchronized void update(final boolean createIfNecessary, final ConfiguredObjectRecord... records)
            throws StoreException
    {
        assertState(State.OPEN);

        if (records.length == 0)
        {
            return;
        }

        for(ConfiguredObjectRecord record : records)
        {
            final UUID id = record.getId();
            final String type = record.getType();

            if(record.getAttributes() == null || !(record.getAttributes().get(ConfiguredObject.NAME) instanceof String))
            {
                throw new StoreException("The record " + id + " of type " + type + " does not have an attribute '"
                                         + ConfiguredObject.NAME
                                         + "' of type String");
            }

            if(_objectsById.containsKey(id))
            {
                final ConfiguredObjectRecord existingRecord = _objectsById.get(id);
                if(!type.equals(existingRecord.getType()))
                {
                    throw new StoreException("Cannot change the type of record " + id + " from type "
                                                + existingRecord.getType() + " to type " + type);
                }
            }
            else if(!createIfNecessary)
            {
                throw new StoreException("Cannot update record with id " + id
                                        + " of type " + type + " as it does not exist");
            }
            else if(!_classNameMapping.containsKey(type))
            {
                throw new StoreException("Cannot update record of unknown type " + type);
            }
        }
        for(ConfiguredObjectRecord record : records)
        {
            record = new ConfiguredObjectRecordImpl(record);
            final UUID id = record.getId();
            final String type = record.getType();
            if(_objectsById.put(id, record) == null)
            {
                List<UUID> idsForType = _idsByType.get(type);
                if(idsForType == null)
                {
                    idsForType = new ArrayList<UUID>();
                    _idsByType.put(type, idsForType);
                }
                if(idsForType.contains(record.getId()))
                {
                    throw new IllegalArgumentException("Duplicate id for record " + record);
                }

                idsForType.add(id);
            }
        }

        save();
    }

    @Override
    public void closeConfigurationStore()
    {

        try
        {
            cleanup();
        }
        finally
        {
            _idsByType.clear();
            _objectsById.clear();
            synchronized (_lock)
            {
                _state = State.CLOSED;
            }
        }
    }

    @Override
    public void onDelete(ConfiguredObject<?> parent)
    {
        FileBasedSettings fileBasedSettings = (FileBasedSettings)parent;

        delete(fileBasedSettings.getStorePath());
    }

    private static Map<String,Class<? extends ConfiguredObject>> generateClassNameMap(final Model model,
                                                                                      final Class<? extends ConfiguredObject> clazz)
    {
        Map<String,Class<? extends ConfiguredObject>>map = new HashMap<String, Class<? extends ConfiguredObject>>();
        if(clazz != null)
        {
            map.put(clazz.getSimpleName(), clazz);
            Collection<Class<? extends ConfiguredObject>> childClasses = model.getChildTypes(clazz);
            if (childClasses != null)
            {
                for (Class<? extends ConfiguredObject> childClass : childClasses)
                {
                    map.putAll(generateClassNameMap(model, childClass));
                }
            }
        }
        return map;
    }

    @Override
    protected ObjectMapper getSerialisationObjectMapper()
    {
        return _objectMapper;
    }

    private void assertState(State state)
    {
        synchronized (_lock)
        {
            if(_state != state)
            {
                throw new IllegalStateException("The store must be in state " + state + " to perform this operation, but it is in state " + _state + " instead");
            }
        }
    }

    private void changeState(State oldState, State newState)
    {
        synchronized (_lock)
        {
            assertState(oldState);
            _state = newState;
        }
    }

}
