/*
 * 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.asterix.common.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.asterix.common.cluster.ClusterPartition;
import org.apache.asterix.common.configuration.AsterixConfiguration;
import org.apache.asterix.common.configuration.Coredump;
import org.apache.asterix.common.configuration.Extension;
import org.apache.asterix.common.configuration.Property;
import org.apache.asterix.common.configuration.Store;
import org.apache.asterix.common.configuration.TransactionLogDir;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.utils.ConfigUtil;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.api.application.IApplicationConfig;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class PropertiesAccessor {
    private static final Logger LOGGER = Logger.getLogger(PropertiesAccessor.class.getName());

    private static final AtomicReference<PropertiesAccessor> instanceHolder = new AtomicReference<>();
    private final String instanceName;
    private final String metadataNodeName;
    private final List<String> nodeNames = new ArrayList<>();;
    private final Map<String, String[]> stores = new HashMap<>();;
    private final Map<String, String> coredumpConfig = new HashMap<>();

    // This can be removed when asterix-configuration.xml is no longer required.
    private final Map<String, Property> asterixConfigurationParams;
    private final IApplicationConfig cfg;
    private final Map<String, String> transactionLogDirs = new HashMap<>();
    private final Map<String, String> asterixBuildProperties = new HashMap<>();
    private final Map<String, ClusterPartition[]> nodePartitionsMap;
    private final SortedMap<Integer, ClusterPartition> clusterPartitions = new TreeMap<>();
    // For extensions
    private final List<AsterixExtension> extensions;

    /**
     * Constructor which reads asterix-configuration.xml, the old way.
     *
     * @throws AsterixException
     * @throws IOException
     */
    private PropertiesAccessor() throws AsterixException, IOException {
        String fileName = System.getProperty(GlobalConfig.CONFIG_FILE_PROPERTY);
        if (fileName == null) {
            fileName = GlobalConfig.DEFAULT_CONFIG_FILE_NAME;
        }
        AsterixConfiguration asterixConfiguration = configure(fileName);
        cfg = null;
        instanceName = asterixConfiguration.getInstanceName();
        metadataNodeName = asterixConfiguration.getMetadataNode();
        List<Store> configuredStores = asterixConfiguration.getStore();
        nodePartitionsMap = new HashMap<>();
        int uniquePartitionId = 0;
        // Here we iterate through all <store> elements in asterix-configuration.xml.
        // For each one, we create an array of ClusterPartitions and store this array
        // in nodePartitionsMap, keyed by the node name. The array is the same length
        // as the comma-separated <storeDirs> child element, because Managix will have
        // arranged for that element to be populated with the full paths to each
        // partition directory (as formed by appending the <store> subdirectory to
        // each <iodevices> path from the user's original cluster.xml).
        for (Store store : configuredStores) {
            String trimmedStoreDirs = store.getStoreDirs().trim();
            String[] nodeStores = trimmedStoreDirs.split(",");
            ClusterPartition[] nodePartitions = new ClusterPartition[nodeStores.length];
            for (int i = 0; i < nodePartitions.length; i++) {
                ClusterPartition partition = new ClusterPartition(uniquePartitionId++, store.getNcId(), i);
                clusterPartitions.put(partition.getPartitionId(), partition);
                nodePartitions[i] = partition;
            }
            stores.put(store.getNcId(), nodeStores);
            nodePartitionsMap.put(store.getNcId(), nodePartitions);
            nodeNames.add(store.getNcId());
        }

        // Get extensions
        extensions = new ArrayList<>();
        if (asterixConfiguration.getExtensions() != null) {
            for (Extension ext : asterixConfiguration.getExtensions().getExtension()) {
                extensions.add(ConfigUtil.toAsterixExtension(ext));
            }
        }

        asterixConfigurationParams = new HashMap<>();
        for (Property p : asterixConfiguration.getProperty()) {
            asterixConfigurationParams.put(p.getName(), p);
        }
        for (Coredump cd : asterixConfiguration.getCoredump()) {
            coredumpConfig.put(cd.getNcId(), cd.getCoredumpPath());
        }
        for (TransactionLogDir txnLogDir : asterixConfiguration.getTransactionLogDir()) {
            transactionLogDirs.put(txnLogDir.getNcId(), txnLogDir.getTxnLogDirPath());
        }
        loadAsterixBuildProperties();
    }

    private AsterixConfiguration configure(String fileName) throws IOException, AsterixException {
        try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)) {
            if (is != null) {
                return configure(is, fileName);
            }
        }
        try (FileInputStream is = new FileInputStream(fileName)) {
            return configure(is, fileName);
        } catch (FileNotFoundException fnf1) {
            LOGGER.warn("Failed to get configuration file " + fileName + " as FileInputStream. FileNotFoundException");
            LOGGER.warn("Attempting to get default configuration file " + GlobalConfig.DEFAULT_CONFIG_FILE_NAME
                    + " as FileInputStream");
            try (FileInputStream fis = new FileInputStream(GlobalConfig.DEFAULT_CONFIG_FILE_NAME)) {
                return configure(fis, GlobalConfig.DEFAULT_CONFIG_FILE_NAME);
            } catch (FileNotFoundException fnf2) {
                fnf1.addSuppressed(fnf2);
                throw new AsterixException("Could not find configuration file " + fileName, fnf1);
            }
        }
    }

    private AsterixConfiguration configure(InputStream is, String fileName) throws AsterixException {
        try {
            JAXBContext ctx = JAXBContext.newInstance(AsterixConfiguration.class);
            Unmarshaller unmarshaller = ctx.createUnmarshaller();
            return (AsterixConfiguration) unmarshaller.unmarshal(is);
        } catch (JAXBException e) {
            throw new AsterixException("Failed to read configuration file " + fileName, e);
        }
    }

    /**
     * Constructor which wraps an IApplicationConfig.
     */
    private PropertiesAccessor(IApplicationConfig cfg) throws AsterixException {
        this.cfg = cfg;
        instanceName = cfg.getString(AsterixProperties.SECTION_ASTERIX, AsterixProperties.PROPERTY_INSTANCE_NAME,
                AsterixProperties.DEFAULT_INSTANCE_NAME);
        nodePartitionsMap = new HashMap<>();
        MutableInt uniquePartitionId = new MutableInt(0);
        extensions = new ArrayList<>();
        // Iterate through each configured NC.
        for (String section : cfg.getSections()) {
            if (section.startsWith(AsterixProperties.SECTION_PREFIX_NC)) {
                configureNc(section, uniquePartitionId);
            } else if (section.startsWith(AsterixProperties.SECTION_PREFIX_EXTENSION)) {
                String className = AsterixProperties.getSectionId(AsterixProperties.SECTION_PREFIX_EXTENSION, section);
                configureExtension(className, section);
            }
        }
        metadataNodeName = getProperty(AsterixProperties.PROPERTY_METADATA_NODE,
                nodeNames.isEmpty() ? "" : nodeNames.get(0), PropertyInterpreters.getStringPropertyInterpreter());
        asterixConfigurationParams = null;
        loadAsterixBuildProperties();
    }

    private void configureExtension(String className, String section) {
        Set<String> keys = cfg.getKeys(section);
        List<Pair<String, String>> kvs = new ArrayList<>();
        for (String key : keys) {
            String value = cfg.getString(section, key);
            kvs.add(new Pair<>(key, value));
        }
        extensions.add(new AsterixExtension(className, kvs));
    }

    private void configureNc(String section, MutableInt uniquePartitionId) {
        String ncId = AsterixProperties.getSectionId(AsterixProperties.SECTION_PREFIX_NC, section);

        // Now we assign the coredump and txnlog directories for this node.
        // QQQ Default values? Should they be specified here? Or should there
        // be a default.ini? Certainly wherever they are, they should be platform-dependent.
        coredumpConfig.put(ncId, cfg.getString(section, AsterixProperties.PROPERTY_COREDUMP_DIR,
                AsterixProperties.DEFAULT_COREDUMP_DIR));
        transactionLogDirs.put(ncId,
                cfg.getString(section, AsterixProperties.PROPERTY_TXN_LOG_DIR, AsterixProperties.DEFAULT_TXN_LOG_DIR));

        // Now we create an array of ClusterPartitions for all the partitions
        // on this NC.
        String[] iodevices = cfg.getString(section, AsterixProperties.PROPERTY_IO_DEV,
                AsterixProperties.DEFAULT_IO_DEV).split(",");
        String storageSubdir = cfg.getString(section, AsterixProperties.PROPERTY_STORAGE_DIR,
                AsterixProperties.DEFAULT_STORAGE_DIR);
        String[] nodeStores = new String[iodevices.length];
        ClusterPartition[] nodePartitions = new ClusterPartition[iodevices.length];
        for (int i = 0; i < nodePartitions.length; i++) {
            // Construct final storage path from iodevice dir + storage subdir.s
            nodeStores[i] = iodevices[i] + File.separator + storageSubdir;
            // Create ClusterPartition instances for this NC.
            ClusterPartition partition = new ClusterPartition(uniquePartitionId.getValue(), ncId, i);
            uniquePartitionId.increment();
            clusterPartitions.put(partition.getPartitionId(), partition);
            nodePartitions[i] = partition;
        }
        stores.put(ncId, nodeStores);
        nodePartitionsMap.put(ncId, nodePartitions);
        nodeNames.add(ncId);
    }

    private void loadAsterixBuildProperties() throws AsterixException {
        Properties gitProperties = new Properties();
        try {
            InputStream propertyStream = getClass().getClassLoader().getResourceAsStream("git.properties");
            if (propertyStream != null) {
                gitProperties.load(propertyStream);
                for (final String name : gitProperties.stringPropertyNames()) {
                    asterixBuildProperties.put(name, gitProperties.getProperty(name));
                }
            } else {
                LOGGER.info("Build properties not found on classpath. Version API will return empty object");
            }
        } catch (IOException e) {
            throw new AsterixException(e);
        }
    }

    public String getMetadataNodeName() {
        return metadataNodeName;
    }

    public Map<String, String[]> getStores() {
        return stores;
    }

    public List<String> getNodeNames() {
        return nodeNames;
    }

    public String getCoredumpPath(String nodeId) {
        return coredumpConfig.get(nodeId);
    }

    public Map<String, String> getTransactionLogDirs() {
        return transactionLogDirs;
    }

    public Map<String, String> getCoredumpConfig() {
        return coredumpConfig;
    }

    public Map<String, String> getBuildProperties() {
        return asterixBuildProperties;
    }

    public <T> T getProperty(String property, T defaultValue, IPropertyInterpreter<T> interpreter) {
        String value;
        Property p = null;
        if (asterixConfigurationParams != null) {
            p = asterixConfigurationParams.get(property);
            value = (p == null) ? null : p.getValue();
        } else {
            value = cfg.getString("app", property);
            if (value == null) {
                value = cfg.getString("asterix", property);
                if (value != null) {
                    LOGGER.warn("[asterix] config section deprecated and will be removed in a future release;" +
                            " please update to [app] (found: " + property + ')');
                }
            }
        }
        if (value == null) {
            return defaultValue;
        }
        try {
            return interpreter.interpret(value);
        } catch (IllegalArgumentException e) {
            if (LOGGER.isEnabledFor(Level.ERROR)) {
                StringBuilder msg = new StringBuilder(
                        "Invalid property value '" + value + "' for property '" + property + "'.\n");
                if (p != null) {
                    msg.append("See the description: \n" + p.getDescription() + "\n");
                }
                msg.append("Default = " + defaultValue);
                LOGGER.error(msg.toString());
            }
            throw e;
        }
    }

    public String getInstanceName() {
        return instanceName;
    }

    public ClusterPartition getMetadataPartition() {
        // metadata partition is always the first partition on the metadata node
        return nodePartitionsMap.get(metadataNodeName)[0];
    }

    public Map<String, ClusterPartition[]> getNodePartitions() {
        return nodePartitionsMap;
    }

    public SortedMap<Integer, ClusterPartition> getClusterPartitions() {
        return clusterPartitions;
    }

    public List<AsterixExtension> getExtensions() {
        return extensions;
    }

    public static PropertiesAccessor getInstance(IApplicationConfig cfg) throws IOException, AsterixException {
        // Determine whether to use old-style asterix-configuration.xml or new-style configuration.
        // QQQ strip this out eventually
        // QQQ this is NOT a good way to determine whether the config is valid
        PropertiesAccessor propertiesAccessor;
        if (cfg != null && cfg.getString("cc", "cluster.address") != null) {
            propertiesAccessor = new PropertiesAccessor(cfg);
        } else {
            propertiesAccessor = new PropertiesAccessor();
        }
        if (!instanceHolder.compareAndSet(null, propertiesAccessor)) {
            propertiesAccessor = instanceHolder.get();
        }
        return propertiesAccessor;
    }

    public static PropertiesAccessor getInstance() throws IOException, AsterixException {
        return getInstance(null);
    }
}
