/*
 * 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.sling.datasource.internal;

import java.lang.management.ManagementFactory;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyOption;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.tomcat.jdbc.pool.ConnectionPool;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(
        name = DataSourceFactory.NAME,
        label = "%datasource.component.name",
        description = "%datasource.component.description",
        metatype = true,
        configurationFactory = true,
        policy = ConfigurationPolicy.REQUIRE
)
public class DataSourceFactory {
    public static final String NAME = "org.apache.sling.datasource.DataSourceFactory";

    @Property
    static final String PROP_DATASOURCE_NAME = "datasource.name";

    @Property(value = PROP_DATASOURCE_NAME)
    static final String PROP_DS_SVC_PROP_NAME = "datasource.svc.prop.name";

    @Property
    static final String PROP_DRIVERCLASSNAME = "driverClassName";

    @Property
    static final String PROP_URL = "url";

    @Property
    static final String PROP_USERNAME = "username";

    @Property(passwordValue = "")
    static final String PROP_PASSWORD = "password";

    /**
     * Value indicating default value should be used. if the value is set to
     * this value then that value would be treated as null
     */
    static final String DEFAULT_VAL = "default";

    @Property(value = DEFAULT_VAL, options = {
            @PropertyOption(name = "Default", value = DEFAULT_VAL),
            @PropertyOption(name = "true", value = "true"),
            @PropertyOption(name = "false", value = "false")})
    static final String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";

    @Property(value = DEFAULT_VAL, options = {
            @PropertyOption(name = "Default", value = DEFAULT_VAL),
            @PropertyOption(name = "true", value = "true"),
            @PropertyOption(name = "false", value = "false")})
    static final String PROP_DEFAULTREADONLY = "defaultReadOnly";

    @Property(value = DEFAULT_VAL, options = {
            @PropertyOption(name = "Default", value = DEFAULT_VAL),
            @PropertyOption(name = "NONE", value = "NONE"),
            @PropertyOption(name = "READ_COMMITTED", value = "READ_COMMITTED"),
            @PropertyOption(name = "READ_UNCOMMITTED", value = "READ_UNCOMMITTED"),
            @PropertyOption(name = "REPEATABLE_READ", value = "REPEATABLE_READ"),
            @PropertyOption(name = "SERIALIZABLE", value = "SERIALIZABLE")})
    static final String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";

    @Property
    static final String PROP_DEFAULTCATALOG = "defaultCatalog";

    @Property(intValue = PoolProperties.DEFAULT_MAX_ACTIVE)
    static final String PROP_MAXACTIVE = "maxActive";

    @Property(intValue = PoolProperties.DEFAULT_MAX_ACTIVE)
    static final String PROP_MAXIDLE = "maxIdle"; //defaults to maxActive

    @Property(intValue = 10)
    static final String PROP_MINIDLE = "minIdle"; //defaults to initialSize

    @Property(intValue = 10)
    static final String PROP_INITIALSIZE = "initialSize";

    @Property(intValue = 30000)
    static final String PROP_MAXWAIT = "maxWait";

    @Property(intValue = 0)
    static final String PROP_MAXAGE = "maxAge";

    @Property(boolValue = false)
    static final String PROP_TESTONBORROW = "testOnBorrow";

    @Property(boolValue = false)
    static final String PROP_TESTONRETURN = "testOnReturn";

    @Property(boolValue = false)
    static final String PROP_TESTWHILEIDLE = "testWhileIdle";

    @Property
    static final String PROP_VALIDATIONQUERY = "validationQuery";

    @Property(intValue = -1)
    static final String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";

    @Property(intValue = 5000)
    protected static final String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";

    @Property(intValue = 60000)
    protected static final String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";

    @Property
    protected static final String PROP_CONNECTIONPROPERTIES = "connectionProperties";

    @Property
    protected static final String PROP_INITSQL = "initSQL";

    @Property(value = "StatementCache;SlowQueryReport(threshold=10000);ConnectionState")
    protected static final String PROP_INTERCEPTORS = "jdbcInterceptors";

    @Property(intValue = 30000)
    protected static final String PROP_VALIDATIONINTERVAL = "validationInterval";

    @Property(boolValue = true)
    protected static final String PROP_LOGVALIDATIONERRORS = "logValidationErrors";

    @Property(value = {}, cardinality = 1024)
    static final String PROP_DATASOURCE_SVC_PROPS = "datasource.svc.properties";

    /**
     * Property names where we need to treat value 'default' as null
     */
    private static final Set<String> PROPS_WITH_DFEAULT =
            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
                    PROP_DEFAULTAUTOCOMMIT,
                    PROP_DEFAULTREADONLY,
                    PROP_DEFAULTTRANSACTIONISOLATION
            )));

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference
    private DriverRegistry driverRegistry;

    private String name;

    private String svcPropName;

    private ObjectName jmxName;

    private ServiceRegistration dsRegistration;

    private DataSource dataSource;

    private BundleContext bundleContext;

    @Activate
    protected void activate(BundleContext bundleContext, Map<String, ?> config) throws Exception {
        this.bundleContext = bundleContext;
        name = getDataSourceName(config);

        checkArgument(name != null, "DataSource name must be specified via [%s] property", PROP_DATASOURCE_NAME);
        dataSource = new LazyJmxRegisteringDataSource(createPoolConfig(config));

        svcPropName = getSvcPropName(config);
        registerDataSource(svcPropName);

        log.info("Created DataSource [{}] with properties {}", name, dataSource.getPoolProperties().toString());
    }

    @Modified
    protected void modified(Map<String, ?> config) throws Exception {
        String name = getDataSourceName(config);
        String svcPropName = getSvcPropName(config);

        if (!this.name.equals(name) || !this.svcPropName.equals(svcPropName)) {
            log.info("Change in datasource name/service property name detected. DataSource would be recreated");
            deactivate();
            activate(bundleContext, config);
            return;
        }

        //Other modifications can be applied at runtime itself
        //Tomcat Connection Pool is decoupled from DataSource so can be closed and reset
        dataSource.setPoolProperties(createPoolConfig(config));
        closeConnectionPool();
        dataSource.createPool();
        log.info("Updated DataSource [{}] with properties {}", name, dataSource.getPoolProperties().toString());
    }

    @Deactivate
    protected void deactivate() {
        if (dsRegistration != null) {
            dsRegistration.unregister();
            dsRegistration = null;
        }

        closeConnectionPool();
        dataSource = null;
    }

    private void closeConnectionPool() {
        unregisterJmx();
        dataSource.close();
    }

    private PoolConfiguration createPoolConfig(Map<String, ?> config) {
        Properties props = new Properties();

        //Copy the other properties first
        Map<String, String> otherProps = PropertiesUtil.toMap(config.get(PROP_DATASOURCE_SVC_PROPS), new String[0]);
        for (Map.Entry<String, String> e : otherProps.entrySet()) {
            set(e.getKey(), e.getValue(), props);
        }

        props.setProperty(org.apache.tomcat.jdbc.pool.DataSourceFactory.OBJECT_NAME, name);

        for (String propName : DummyDataSourceFactory.getPropertyNames()) {
            String value = PropertiesUtil.toString(config.get(propName), null);
            set(propName, value, props);
        }

        //Specify the DataSource such that connection creation logic is handled
        //by us where we take care of OSGi env
        PoolConfiguration poolProperties = org.apache.tomcat.jdbc.pool.DataSourceFactory.parsePoolProperties(props);
        poolProperties.setDataSource(createDriverDataSource(poolProperties));

        return poolProperties;
    }

    private DriverDataSource createDriverDataSource(PoolConfiguration poolProperties) {
        return new DriverDataSource(poolProperties, driverRegistry, bundleContext, this);
    }

    private void registerDataSource(String svcPropName) {
        Dictionary<String, Object> svcProps = new Hashtable<String, Object>();
        svcProps.put(svcPropName, name);
        svcProps.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
        svcProps.put(Constants.SERVICE_DESCRIPTION, "DataSource service based on Tomcat JDBC");
        dsRegistration = bundleContext.registerService(javax.sql.DataSource.class, dataSource, svcProps);
    }

    private void registerJmx(ConnectionPool pool) throws SQLException {
        org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmxPool = pool.getJmxPool();
        if (jmxPool == null) {
            //jmx not enabled
            return;
        }
        Hashtable<String, String> table = new Hashtable<String, String>();
        table.put("type", "ConnectionPool");
        table.put("class", javax.sql.DataSource.class.getName());
        table.put("name", ObjectName.quote(name));

        try {
            jmxName = new ObjectName("org.apache.sling", table);
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            mbs.registerMBean(jmxPool, jmxName);
        } catch (Exception e) {
            log.warn("Error occurred while registering the JMX Bean for " +
                    "connection pool with name {}", jmxName, e);
        }
    }

    ConnectionPool getPool() {
        return dataSource.getPool();
    }

    private void unregisterJmx() {
        try {
            if (jmxName != null) {
                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
                mbs.unregisterMBean(jmxName);
            }
        } catch (InstanceNotFoundException ignore) {
            // NOOP
        } catch (Exception e) {
            log.error("Unable to unregister JDBC pool with JMX", e);
        }
    }

    //~----------------------------------------< Config Handling >

    static String getDataSourceName(Map<String, ?> config) {
        return PropertiesUtil.toString(config.get(PROP_DATASOURCE_NAME), null);
    }

    static String getSvcPropName(Map<String, ?> config) {
        return PropertiesUtil.toString(config.get(PROP_DS_SVC_PROP_NAME), PROP_DATASOURCE_NAME);
    }

    private static void set(String name, String value, Properties props) {
        if (PROPS_WITH_DFEAULT.contains(name) && DEFAULT_VAL.equals(value)) {
            value = null;
        }

        if (value != null) {
            value = value.trim();
        }

        if (value != null && !value.isEmpty()) {
            props.setProperty(name, value);
        }
    }

    static void checkArgument(boolean expression,
                                      String errorMessageTemplate,
                                      Object... errorMessageArgs) {
        if (!expression) {
            throw new IllegalArgumentException(
                    String.format(errorMessageTemplate, errorMessageArgs));
        }
    }

    private class LazyJmxRegisteringDataSource extends org.apache.tomcat.jdbc.pool.DataSource {
        private volatile boolean initialized;

        public LazyJmxRegisteringDataSource(PoolConfiguration poolProperties) {
            super(poolProperties);
        }

        @Override
        public ConnectionPool createPool() throws SQLException {
            ConnectionPool pool = super.createPool();
            registerJmxLazily(pool);
            return pool;
        }

        @Override
        public void close() {
            initialized = false;
            super.close();
        }

        private void registerJmxLazily(ConnectionPool pool) throws SQLException {
            if (!initialized) {
                synchronized (this) {
                    if (initialized) {
                        return;
                    }
                    DataSourceFactory.this.registerJmx(pool);
                    initialized = true;
                }
            }
        }
    }

    /**
     * Dummy impl to enable access to protected fields
     */
    private static class DummyDataSourceFactory extends org.apache.tomcat.jdbc.pool.DataSourceFactory {
        static String[] getPropertyNames() {
            return ALL_PROPERTIES;
        }
    }
}
