/*
 * 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.ode.il.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.utils.SystemUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;

/**
 * Configuration object used for configuring the intergration layer. The propereties are those likely to be common to all layers.
 *
 * @author mszefler
 */
public class OdeConfigProperties {
    private static final long serialVersionUID = 1L;

    private static final Logger __log = LoggerFactory.getLogger(OdeConfigProperties.class);

    public static final String PROP_DB_MODE = "db.mode";

    public static final String PROP_DB_EXTERNAL_DS = "db.ext.dataSource";

    public static final String PROP_DB_EMBEDDED_NAME = "db.emb.name";

    public static final String PROP_DB_EMBEDDED_TYPE = "db.emb.type";

    public static final String PROP_DB_EMBEDDED_CREATE = "db.emb.create";
    
    public static final String PROP_DB_INTERNAL_URL = "db.int.jdbcurl";

    public static final String PROP_DB_INTERNAL_DRIVER = "db.int.driver";

    public static final String PROP_DB_INTERNAL_PASSWORD = "db.int.password";

    public static final String PROP_DB_INTERNAL_USER = "db.int.username";

    public static final String PROP_DB_LOGGING = "db.logging";

    public static final String PROP_TX_FACTORY_CLASS = "tx.factory.class";

    public static final String PROP_POOL_MAX = "db.pool.max";

    public static final String PROP_POOL_MIN = "db.pool.min";

    public static final String PROP_DB_POOL_BLOCKING = "db.pool.blocking";

    public static final String PROP_THREAD_POOL_SIZE = "threads.pool.size";

    public static final String PROP_CONNECTOR_PORT = "jca.port";

    public static final String PROP_CONNECTOR_NAME = "jca.name";

    public static final String PROP_WORKING_DIR = "working.dir";

    public static final String PROP_DEPLOY_DIR = "deploy.dir";

    public static final String PROP_EVENT_LISTENERS = "event.listeners";

    public static final String PROP_MEX_INTERCEPTORS = "mex.interceptors";

    public static final String PROP_MEX_INMEM_TTL = "mex.inmem.ttl";

    public static final String PROP_PROCESS_DEHYDRATION = "process.dehydration";

    public static final String PROP_PROCESS_DEHYDRATION_MAXIMUM_AGE = "process.dehydration.maximum.age";

    public static final String PROP_PROCESS_DEHYDRATION_MAXIMUM_COUNT = "process.dehydration.maximum.count";

    public static final String PROP_PROCESS_HYDRATION_LAZY = "process.hydration.lazy";

    public static final String PROP_PROCESS_HYDRATION_LAZY_MINIMUM_SIZE = "process.hydration.lazy.minimum.size";

    public static final String PROP_PROCESS_HYDRATION_THROTTLED_MAXIMUM_COUNT = "process.hydration.throttled.maximum.count";

    public static final String PROP_PROCESS_HYDRATION_THROTTLED_MAXIMUM_SIZE = "process.hydration.throttled.maximum.size";

    public static final String PROP_PROCESS_INSTANCE_THROTTLED_MAXIMUM_COUNT = "process.instance.throttled.maximum.count";

    public static final String PROP_DAOCF = "dao.factory";

    public static final String PROP_MIGRATION_TRANSACTION_TIMEOUT = "migration.transaction.timeout";

    public static final String DEFAULT_TX_FACTORY_CLASS_NAME = "org.apache.ode.il.EmbeddedGeronimoFactory";

    public static final String PROP_CLUSTERING_ENABLED = "clustering.enabled";

    public static final String PROP_CLUSTERING_IMPL_CLASS = "clustering.impl.class";

    public static final String DEFAULT_CLUSTERING_IMPL_CLASS_NAME = "org.apache.ode.clustering.hazelcast.HazelcastClusterImpl";

    private File _cfgFile;

    private String _prefix;

    private Properties _props;

    /** Default defaults for the database embedded name and dao connection factory class. */
    private static String __dbEmbName = "jpadb";
    private static String __daoCfClass = "org.apache.ode.dao.jpa.BPELDAOConnectionFactoryImpl";

    public static String DEFAULT_DB_EMB_NAME = "ode-db";
    public static String DEFAULT_DB_EMB_TYPE = "h2";
    public static String DEFAULT_DAOCF_CLASS = "org.apache.ode.dao.jpa.openjpa.BpelDAOConnectionFactoryImpl";

    static {
        String odep = System.getProperty("ode.persistence");
        if (odep != null &&
                "hibernate".equalsIgnoreCase(odep)) {
            __log.debug("Using HIBERNATE due to system property override!");
            __dbEmbName = "hibdb";
            __daoCfClass = "org.apache.ode.daohib.bpel.BpelDAOConnectionFactoryImpl";

        }
    }
    /**
     * Possible database modes.
     */
    public enum DatabaseMode {
        /** External data-source (managed by app server) */
        EXTERNAL,

        /** Internal data-source (User provides database info, Ode provides connection pool) */
        INTERNAL,

        /** Embedded database (Ode provides default embedded database with connection pool) */
        EMBEDDED
    }
    
    /**
     * Possible database implementation.
     */
    public enum EmbeddedDbType {
        
        DERBY,
        
        H2
    }


    public OdeConfigProperties(File cfgFile, String prefix) {
        _cfgFile = cfgFile;
        _prefix = prefix;
        _props = new Properties();
    }

    public OdeConfigProperties(Properties props, String prefix) {
        _cfgFile = null;
        _prefix = prefix;
        _props = props;
    }

    public File getFile() {
        return _cfgFile;
    }

    public void load() throws IOException {
        if (_cfgFile.exists()) {
            __log.debug("config file exists: " + _cfgFile);
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(_cfgFile);
                _props.load(fis);
            } finally {
                if (fis != null)
                    try {
                        fis.close();
                    } catch (Exception ex) {
                        __log.error(ex.getMessage(), ex);
                    }
            }
        } else {
            __log.debug("config file does not exists: " + _cfgFile);
            throw new FileNotFoundException("" + _cfgFile);
        }
        for (Object key : _props.keySet()) {
            String value = (String) _props.get(key);
            value = SystemUtils.replaceSystemProperties(value);
            _props.put(key, value);
        }
    }

    /**
     * Should the internal database be used, or are the datasources provided?
     *
     * @return db mode
     */
    public String getDbEmbeddedName() {
        return getProperty(OdeConfigProperties.PROP_DB_EMBEDDED_NAME, __dbEmbName);

    }
    
    public EmbeddedDbType getDbEmbeddedType() {
        return EmbeddedDbType.valueOf(getProperty(OdeConfigProperties.PROP_DB_EMBEDDED_TYPE, DEFAULT_DB_EMB_TYPE).trim().toUpperCase());
    }

    public boolean isDbEmbeddedCreate() {
        return Boolean.valueOf(getProperty(OdeConfigProperties.PROP_DB_EMBEDDED_CREATE, "true"));
    }

    public DatabaseMode getDbMode() {
        return DatabaseMode.valueOf(getProperty(OdeConfigProperties.PROP_DB_MODE, DatabaseMode.EMBEDDED.toString()).trim()
                .toUpperCase());
    }

    public String getDAOConnectionFactory() {
        return getProperty(PROP_DAOCF, __daoCfClass);
    }

    public String getDbDataSource() {
        return getProperty(OdeConfigProperties.PROP_DB_EXTERNAL_DS, "java:comp/env/jdbc/ode-ds");
    }

    public String getDbIntenralJdbcUrl() {
        return getProperty(OdeConfigProperties.PROP_DB_INTERNAL_URL, "jdbc:derby://localhost/ode");
    }

    public String getDbInternalMCFClass() {
        return getProperty("db.int.mcf");
    }

    public Properties getDbInternalMCFProperties() {
        String prefix = _prefix + "db.int.mcf.";
        Properties p = new Properties();
        for (Map.Entry<Object, Object> e : _props.entrySet()) {
            String s = "" + e.getKey();
            if (s.startsWith(prefix)) {
                p.put(s.substring(prefix.length()), e.getValue());
            }
        }
        return p;
    }

    /**
     * JDBC driver class (for use in INTERNAL mode).
     *
     * @return
     */
    public String getDbInternalJdbcDriverClass() {
        return getProperty(OdeConfigProperties.PROP_DB_INTERNAL_DRIVER, "org.apache.derby.jdbc.ClientDriver");
    }

    public boolean getPoolBlocking() {
        return Boolean.valueOf(getProperty(PROP_DB_POOL_BLOCKING,"false"));
    }

    public int getThreadPoolMaxSize() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_THREAD_POOL_SIZE, "0"));
    }

    public int getPoolMaxSize() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_POOL_MAX, "10"));
    }

    public int getPoolMinSize() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_POOL_MIN, "1"));
    }

    public int getConnectorPort() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_CONNECTOR_PORT, "2099"));
    }

    public String getConnectorName() {
        return getProperty(OdeConfigProperties.PROP_CONNECTOR_NAME, "ode");
    }

    public String getWorkingDir() {
        return getProperty(OdeConfigProperties.PROP_WORKING_DIR);
    }

    public String getDeployDir() {
        return getProperty(OdeConfigProperties.PROP_DEPLOY_DIR);
    }

    public boolean isClusteringEnabled() {
        return Boolean.valueOf(getProperty(OdeConfigProperties.PROP_CLUSTERING_ENABLED, "false"));
    }

    public String getClusteringImplClass() {
        return getProperty(OdeConfigProperties.PROP_CLUSTERING_IMPL_CLASS, DEFAULT_CLUSTERING_IMPL_CLASS_NAME);
    }

    public String getTxFactoryClass() {
        return getProperty(OdeConfigProperties.PROP_TX_FACTORY_CLASS, DEFAULT_TX_FACTORY_CLASS_NAME);
    }

    public String getEventListeners() {
        return getProperty(PROP_EVENT_LISTENERS);
    }

    public String getMessageExchangeInterceptors() {
        return getProperty(PROP_MEX_INTERCEPTORS);
    }

    public long getInMemMexTtl() {
        return Long.valueOf(getProperty(PROP_MEX_INMEM_TTL, ""+10*60*1000));
    }

    public boolean isDehydrationEnabled() {
        return Boolean.valueOf(getProperty(OdeConfigProperties.PROP_PROCESS_DEHYDRATION, "false"));
    }

    public long getDehydrationMaximumAge() {
        return Long.valueOf(getProperty(PROP_PROCESS_DEHYDRATION_MAXIMUM_AGE, ""+20*60*1000));
    }

    public int getDehydrationMaximumCount() {
        return Integer.valueOf(getProperty(PROP_PROCESS_DEHYDRATION_MAXIMUM_COUNT, ""+1000));
    }

    public boolean isHydrationLazy() {
        return Boolean.valueOf(getProperty(OdeConfigProperties.PROP_PROCESS_HYDRATION_LAZY, "true"));
    }

    public int getHydrationLazyMinimumSize() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_PROCESS_HYDRATION_LAZY_MINIMUM_SIZE, String.valueOf(0)));
    }

    public int getProcessThrottledMaximumCount() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_PROCESS_HYDRATION_THROTTLED_MAXIMUM_COUNT, String.valueOf(Integer.MAX_VALUE)));
    }

    public int getInstanceThrottledMaximumCount() {
        return Integer.valueOf(getProperty(OdeConfigProperties.PROP_PROCESS_INSTANCE_THROTTLED_MAXIMUM_COUNT, String.valueOf(Integer.MAX_VALUE)));
    }

    public long getProcessThrottledMaximumSize() {
        return Long.valueOf(getProperty(OdeConfigProperties.PROP_PROCESS_HYDRATION_THROTTLED_MAXIMUM_SIZE, String.valueOf(Long.MAX_VALUE)));
    }

    public boolean isProcessSizeThrottled() {
        return getProcessThrottledMaximumSize() == Long.MAX_VALUE;
    }

    public boolean isDbLoggingEnabled() {
        return Boolean.valueOf(getProperty(OdeConfigProperties.PROP_DB_LOGGING, "false"));
    }


    public String getProperty(String pname) {
        return _props.getProperty(_prefix + pname);
    }

    public String getProperty(String key, String dflt) {
        return _props.getProperty(_prefix + key, dflt);
    }

    public Properties getProperties() {
        return _props;
    }

    public String getDbInternalUserName() {
        return getProperty(PROP_DB_INTERNAL_USER);
    }

    public String getDbInternalPassword() {
        return getProperty(PROP_DB_INTERNAL_PASSWORD);
    }

    public int getMigrationTransactionTimeout() {
        return Integer.valueOf(getProperty(PROP_MIGRATION_TRANSACTION_TIMEOUT, String.valueOf(0)));
    }

}
