/*
 * 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 WARRANTIESOR 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.aries.tx.control.jdbc.xa.impl;

import static java.util.Arrays.asList;
import static org.apache.aries.tx.control.jdbc.common.impl.AbstractInternalJDBCConnectionProviderFactory.toBoolean;
import static org.osgi.framework.Constants.OBJECTCLASS;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_DATABASE_NAME;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_DATASOURCE_NAME;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_DESCRIPTION;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_NETWORK_PROTOCOL;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_PASSWORD;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_PORT_NUMBER;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_ROLE_NAME;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_SERVER_NAME;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_URL;
import static org.osgi.service.jdbc.DataSourceFactory.JDBC_USER;
import static org.osgi.service.jdbc.DataSourceFactory.OSGI_JDBC_DRIVER_CLASS;
import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.OSGI_RECOVERY_IDENTIFIER;
import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.XA_ENLISTMENT_ENABLED;

import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.aries.tx.control.jdbc.common.impl.AbstractJDBCConnectionProvider;
import org.apache.aries.tx.control.resource.common.impl.ConfigurationDefinedResourceFactory;
import org.apache.aries.tx.control.resource.common.impl.LifecycleAware;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.jdbc.DataSourceFactory;
import org.osgi.service.transaction.control.jdbc.JDBCConnectionProvider;
import org.osgi.service.transaction.control.recovery.RecoverableXAResource;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ManagedServiceFactoryImpl extends ConfigurationDefinedResourceFactory {

	private static final Logger LOG = LoggerFactory.getLogger(ManagedServiceFactoryImpl.class);
	
	private static final String DSF_TARGET_FILTER = "aries.dsf.target.filter";
	private static final String JDBC_PROP_NAMES = "aries.jdbc.property.names";
	private static final List<String> JDBC_PROPERTIES = asList(JDBC_DATABASE_NAME, JDBC_DATASOURCE_NAME,
			JDBC_DESCRIPTION, JDBC_NETWORK_PROTOCOL, JDBC_PASSWORD, JDBC_PORT_NUMBER, JDBC_ROLE_NAME, JDBC_SERVER_NAME,
			JDBC_URL, JDBC_USER);

	public ManagedServiceFactoryImpl(BundleContext context) {
		super(context);
	}

	@Override
	public String getName() {
		return "Aries JDBCConnectionProvider (XA enabled) service";
	}

	@Override
	protected LifecycleAware getConfigurationDrivenResource(BundleContext context, 
			String pid, Map<String, Object> properties) throws Exception {
		Properties jdbcProps = getJdbcProps(pid, properties);
	
		try {
			return new ManagedJDBCResourceProvider(context, pid, jdbcProps, properties);
		} catch (InvalidSyntaxException e) {
			LOG.error("The configuration {} contained an invalid target filter {}", pid, e.getFilter());
			throw new ConfigurationException(DSF_TARGET_FILTER, "The target filter was invalid", e);
		}
	}

	@SuppressWarnings("unchecked")
	private Properties getJdbcProps(String pid, Map<String, Object> properties) throws ConfigurationException {

		Object object = properties.getOrDefault(JDBC_PROP_NAMES, JDBC_PROPERTIES);
		Collection<String> propnames;
		if (object instanceof String) {
			propnames = Arrays.asList(((String) object).split(","));
		} else if (object instanceof String[]) {
			propnames = Arrays.asList((String[]) object);
		} else if (object instanceof Collection) {
			propnames = (Collection<String>) object;
		} else {
			LOG.error("The configuration {} contained an invalid list of JDBC property names", pid, object);
			throw new ConfigurationException(JDBC_PROP_NAMES,
					"The jdbc property names must be a String+ or comma-separated String");
		}

		Properties p = new Properties();

		propnames.stream().filter(properties::containsKey)
				.forEach(s -> p.setProperty(s, String.valueOf(properties.get(s))));

		return p;
	}

	private static class ManagedJDBCResourceProvider
			implements ServiceTrackerCustomizer<DataSourceFactory, DataSourceFactory>, LifecycleAware {

		private final BundleContext context;
		private final String pid;
		private final Properties jdbcProperties;
		private final Map<String, Object> providerProperties;
		private final ServiceTracker<DataSourceFactory, DataSourceFactory> dsfTracker;

		private DataSourceFactory activeDsf;
		private ServiceRegistration<JDBCConnectionProvider> serviceReg;
		private ServiceRegistration<RecoverableXAResource> recoveryReg;
		private AbstractJDBCConnectionProvider provider;

		public ManagedJDBCResourceProvider(BundleContext context, String pid, Properties jdbcProperties,
				Map<String, Object> providerProperties) throws InvalidSyntaxException, ConfigurationException {
			this.context = context;
			this.pid = pid;
			this.jdbcProperties = jdbcProperties;
			this.providerProperties = providerProperties;

			String targetFilter = (String) providerProperties.get(DSF_TARGET_FILTER);
			if (targetFilter == null) {
				String driver = (String) providerProperties.get(OSGI_JDBC_DRIVER_CLASS);
				if (driver == null) {
					LOG.error("The configuration {} must specify a target filter or a JDBC driver class", pid);
					throw new ConfigurationException(OSGI_JDBC_DRIVER_CLASS,
							"The configuration must specify either a target filter or a JDBC driver class");
				}
				targetFilter = "(&(" + OBJECTCLASS + "=" + DataSourceFactory.class.getName() + ")(" + OSGI_JDBC_DRIVER_CLASS + "=" + driver + "))";
			}

			targetFilter = "(&(" + OBJECTCLASS + "=" + DataSourceFactory.class.getName() + ")" + targetFilter + ")";

			this.dsfTracker = new ServiceTracker<>(context, context.createFilter(targetFilter), this);
		}

		public void start() {
			dsfTracker.open();
		}

		public void stop() {
			dsfTracker.close();
		}

		@Override
		public DataSourceFactory addingService(ServiceReference<DataSourceFactory> reference) {
			DataSourceFactory service = context.getService(reference);
			return updateService(service);
		}

		private DataSourceFactory updateService(DataSourceFactory service) {
			boolean setDsf;
			synchronized (this) {
				setDsf = activeDsf == null;
				if(setDsf)
					activeDsf = service;
			}

			ServiceRegistration<JDBCConnectionProvider> reg = null;
			ServiceRegistration<RecoverableXAResource> reg2 = null;
			JDBCConnectionProviderImpl provider = null;
			if (setDsf) {
				try {
					provider = new JDBCConnectionProviderFactoryImpl().getProviderFor(service,
							jdbcProperties, providerProperties);
					String recoveryId = (String) providerProperties.get(OSGI_RECOVERY_IDENTIFIER);
					if(recoveryId !=null) {
						if(toBoolean(providerProperties, XA_ENLISTMENT_ENABLED, true)) {
							LOG.warn("A JDBCResourceProvider has been configured with a recovery identifier {} but it has also been configured not to use XA transactions. No recovery will be available.", recoveryId);
						} else {
							reg2 = context.registerService(RecoverableXAResource.class, 
									new RecoverableXAResourceImpl(recoveryId, provider, 
											(String) providerProperties.get("recovery.user"),
											(String) providerProperties.get(".recovery.password)")), 
									getServiceProperties());
						}
					}
					reg = context
							.registerService(JDBCConnectionProvider.class, provider, getServiceProperties());

					ServiceRegistration<JDBCConnectionProvider> oldReg;
					ServiceRegistration<RecoverableXAResource> oldReg2;
					AbstractJDBCConnectionProvider oldProvider;
					synchronized (this) {
						if(activeDsf == service) {
							oldReg = serviceReg;
							serviceReg = reg;
							oldReg2 = recoveryReg;
							recoveryReg = reg2;
							oldProvider = this.provider;
							this.provider = provider;
						} else {
							oldReg = reg;
							oldReg2 = reg2;
							oldProvider = provider;
						}
					}
					safeUnregister(oldReg);
					safeUnregister(oldReg2);
					safeClose(oldProvider);
				} catch (Exception e) {
					LOG.error("An error occurred when creating the connection provider for {}.", pid, e);
					
					synchronized (this) {
						if(activeDsf == service) {
							activeDsf = null;
						}
					}
					safeUnregister(reg);
					safeUnregister(reg2);
					safeClose(provider);
				}
			}
			return service;
		}

		private void safeUnregister(ServiceRegistration<?> reg) {
			if(reg != null) {
				try {
					reg.unregister();
				} catch (IllegalStateException ise) {
					LOG.debug("An exception occurred when unregistering a service for {}", pid);
				}
			}
		}
			
		private void safeClose(AbstractJDBCConnectionProvider oldProvider) {
			if(oldProvider != null) {
				try {
					oldProvider.close();
				} catch (Exception e) {
					LOG.debug("An exception occurred when closing a provider for {}", pid, e);
				}
			}
		}

		private Dictionary<String, ?> getServiceProperties() {
			Hashtable<String, Object> props = new Hashtable<>();
			providerProperties.keySet().stream()
					.filter(s -> !s.startsWith("."))
					.filter(s -> !JDBC_PASSWORD.equals(s))
					.forEach(s -> props.put(s, providerProperties.get(s)));
			return props;
		}

		@Override
		public void modifiedService(ServiceReference<DataSourceFactory> reference, DataSourceFactory service) {
		}

		@Override
		public void removedService(ServiceReference<DataSourceFactory> reference, DataSourceFactory service) {
			boolean dsfLeft;
			ServiceRegistration<JDBCConnectionProvider> oldReg = null;
			ServiceRegistration<RecoverableXAResource> oldReg2 = null;
			AbstractJDBCConnectionProvider oldProvider = null;
			synchronized (this) {
				dsfLeft = activeDsf == service;
				if (dsfLeft) {
					activeDsf = null;
					oldReg = serviceReg;
					oldReg2 = recoveryReg;
					oldProvider = provider;
					serviceReg = null;
					recoveryReg = null;
					provider = null;
				}
			}
			safeUnregister(oldReg);
			safeUnregister(oldReg2);
			safeClose(oldProvider);

			if (dsfLeft) {
				DataSourceFactory newDSF = dsfTracker.getService();
				if (newDSF != null) {
					updateService(dsfTracker.getService());
				}
			}
		}
	}
}
