/*******************************************************************************
 * Copyright (c) 2005, 2018 Cognos Incorporated, IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     Cognos Incorporated - initial API and implementation
 *     IBM Corporation - bug fixes and enhancements
 *******************************************************************************/
package org.eclipse.equinox.internal.cm;

import java.util.*;
import org.osgi.framework.*;
import org.osgi.service.cm.*;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;

/**
 * ManagedServiceTracker tracks... ManagedServices and notifies them about related configuration changes
 */
class ManagedServiceTracker extends ServiceTracker<ManagedService, ManagedService> {

	final ConfigurationAdminFactory configurationAdminFactory;
	private final ConfigurationStore configurationStore;

	/** @GuardedBy targets*/
	private final TargetMap targets = new TargetMap();

	private final SerializedTaskQueue queue = new SerializedTaskQueue("ManagedService Update Queue"); //$NON-NLS-1$

	public ManagedServiceTracker(ConfigurationAdminFactory configurationAdminFactory, ConfigurationStore configurationStore, BundleContext context) {
		super(context, ManagedService.class.getName(), null);
		this.configurationAdminFactory = configurationAdminFactory;
		this.configurationStore = configurationStore;
	}

	void notifyDeleted(ConfigurationImpl config) {
		config.checkLocked();
		String configLoc = config.getLocation();
		if (configLoc == null) {
			return;
		}
		boolean isMultiple = configLoc.startsWith("?"); //$NON-NLS-1$
		String pid = config.getPid(false);
		List<ServiceReference<ManagedService>> references = getManagedServiceReferences(pid);
		for (ServiceReference<ManagedService> ref : references) {
			if (!hasMoreSpecificConfigPids(ref, pid)) {
				boolean hasLocPermission = configurationAdminFactory.checkTargetPermission(configLoc, ref);
				ManagedService service = getService(ref);
				if (hasLocPermission && service != null) {
					if (isMultiple || ConfigurationAdminImpl.getLocation(ref.getBundle()).equals(configLoc)) {
						// search for other matches
						List<List<String>> qualifiedPidLists;
						synchronized (targets) {
							qualifiedPidLists = targets.getQualifiedPids(ref);
						}
						updateManagedService(qualifiedPidLists, ref, service);
					}
				}
			}
		}
	}

	void notifyUpdated(ConfigurationImpl config) {
		config.checkLocked();
		String configLoc = config.getLocation();
		boolean isMultiple = configLoc != null && configLoc.startsWith("?"); //$NON-NLS-1$
		String pid = config.getPid();
		List<ServiceReference<ManagedService>> references = getManagedServiceReferences(pid);
		for (ServiceReference<ManagedService> ref : references) {
			if (!hasMoreSpecificConfigPids(ref, pid)) {
				boolean hasLocPermission = configurationAdminFactory.checkTargetPermission(configLoc, ref);
				ManagedService service = getService(ref);
				if (hasLocPermission && service != null) {
					if (isMultiple || config.bind(ConfigurationAdminImpl.getLocation(ref.getBundle()))) {
						Dictionary<String, Object> properties = config.getProperties();
						configurationAdminFactory.modifyConfiguration(ref, properties);
						asynchUpdated(service, properties);
					}
				}
			}
		}
	}

	void notifyUpdateLocation(ConfigurationImpl config, String oldLocation) {
		config.checkLocked();
		String configLoc = config.getLocation();
		if (configLoc == null ? oldLocation == null : configLoc.equals(oldLocation)) {
			// same location do nothing
			return;
		}
		boolean oldIsMultiple = oldLocation != null && oldLocation.startsWith("?"); //$NON-NLS-1$
		boolean newIsMultiple = configLoc != null && configLoc.startsWith("?"); //$NON-NLS-1$
		String pid = config.getPid();
		List<ServiceReference<ManagedService>> references = getManagedServiceReferences(pid);
		for (ServiceReference<ManagedService> ref : references) {
			if (!hasMoreSpecificConfigPids(ref, pid)) {
				boolean hasOldPermission = configurationAdminFactory.checkTargetPermission(oldLocation, ref);
				boolean hasNewPermission = configurationAdminFactory.checkTargetPermission(configLoc, ref);
				ManagedService service = getService(ref);
				if (service != null) {
					boolean delete = false;
					boolean update = false;
					String targetLocation = ConfigurationAdminImpl.getLocation(ref.getBundle());
					if (hasOldPermission != hasNewPermission) {
						if (hasOldPermission) {
							delete = oldIsMultiple || targetLocation.equals(oldLocation);
						} else {
							update = newIsMultiple || config.bind(targetLocation);
						}
					} else {
						// location has changed, this may be a bound configuration
						if (targetLocation.equals(oldLocation)) {
							delete = true;
						} else {
							update = newIsMultiple || config.bind(targetLocation);
						}
					}
					if (delete) {
						// search for other matches
						List<List<String>> qualifiedPidLists;
						synchronized (targets) {
							qualifiedPidLists = targets.getQualifiedPids(ref);
						}
						updateManagedService(qualifiedPidLists, ref, service);
					} else if (update) {
						Dictionary<String, Object> properties = config.getProperties();
						configurationAdminFactory.modifyConfiguration(ref, properties);
						asynchUpdated(service, properties);
					}
					// do not break on !isMultiple since we need to check if the other refs apply no matter what
				}
			}
		}
	}

	private boolean hasMoreSpecificConfigPids(ServiceReference<ManagedService> ref, String pid) {
		List<List<String>> qualifiedPidsLists;
		synchronized (targets) {
			qualifiedPidsLists = targets.getQualifiedPids(ref);
		}
		for (List<String> qualifiedPids : qualifiedPidsLists) {
			for (String qualifiedPid : qualifiedPids) {
				if (qualifiedPid.length() <= pid.length() || !qualifiedPid.startsWith(pid)) {
					break;
				}
				ConfigurationImpl config = configurationStore.findConfiguration(qualifiedPid);
				if (config != null) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public ManagedService addingService(ServiceReference<ManagedService> reference) {
		ManagedService service = context.getService(reference);
		if (service == null)
			return null;

		addReference(reference, service);
		return service;
	}

	@Override
	public void modifiedService(ServiceReference<ManagedService> reference, ManagedService service) {
		List<String> newPids = TargetMap.getPids(reference.getProperty(Constants.SERVICE_PID));
		synchronized (targets) {
			List<List<String>> previousPids = targets.getQualifiedPids(reference);
			if (newPids.size() == previousPids.size()) {
				boolean foundAll = false;
				for (String newPid : newPids) {
					foundAll = false;
					for (List<String> pids : previousPids) {
						if (pids.contains(newPid)) {
							foundAll = true;
							break;
						}
					}
					if (!foundAll) {
						break;
					}
				}
				if (foundAll) {
					return;
				}
			}
		}

		untrackManagedService(reference);
		addingService(reference);
	}

	@Override
	public void removedService(ServiceReference<ManagedService> reference, ManagedService service) {
		untrackManagedService(reference);

		context.ungetService(reference);
	}

	private void addReference(ServiceReference<ManagedService> reference, ManagedService service) {
		List<List<String>> qualifiedPidLists = trackManagedService(reference);
		updateManagedService(qualifiedPidLists, reference, service);
	}

	private void updateManagedService(List<List<String>> qualifiedPidLists, ServiceReference<ManagedService> reference, ManagedService service) {
		for (List<String> qualifiedPids : qualifiedPidLists) {
			boolean foundConfig = false;
			qualifiedPids: for (String qualifiedPid : qualifiedPids) {
				ConfigurationImpl config = configurationStore.findConfiguration(qualifiedPid);
				if (config != null) {
					try {
						config.lock();
						if (!config.isDeleted()) {
							if (config.getFactoryPid() != null) {
								configurationAdminFactory.log(LogService.LOG_WARNING, "Configuration for " + Constants.SERVICE_PID + "=" + qualifiedPid + " should only be used by a " + ManagedServiceFactory.class.getName()); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
							}
							String location = config.getLocation();
							boolean shouldBind = location == null || !location.startsWith("?"); //$NON-NLS-1$
							boolean hasLocPermission = configurationAdminFactory.checkTargetPermission(location, reference);
							if (hasLocPermission) {
								if ((shouldBind && config.bind(ConfigurationAdminImpl.getLocation(reference.getBundle()))) || !shouldBind) {
									Dictionary<String, Object> properties = config.getProperties();
									configurationAdminFactory.modifyConfiguration(reference, properties);
									asynchUpdated(service, properties);
									foundConfig = true;
									break qualifiedPids;
								}
								configurationAdminFactory.log(LogService.LOG_WARNING, "Configuration for " + Constants.SERVICE_PID + "=" + qualifiedPid + " could not be bound to " + ConfigurationAdminImpl.getLocation(reference.getBundle())); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
							}
						}
					} finally {
						config.unlock();
					}
				}
			}
			if (!foundConfig) {
				// This seems questionable to me, but is required for the spec.
				// if a ManagedService has multiple pids, watch out!!
				asynchUpdated(service, null);
			}
		}
	}

	private List<List<String>> trackManagedService(ServiceReference<ManagedService> reference) {
		synchronized (targets) {
			return targets.add(reference);
		}
	}

	private void untrackManagedService(ServiceReference<ManagedService> reference) {
		synchronized (targets) {
			targets.remove(reference);
		}
	}

	private List<ServiceReference<ManagedService>> getManagedServiceReferences(String pid) {
		synchronized (targets) {
			@SuppressWarnings("rawtypes")
			List temp = targets.getTargets(pid);
			@SuppressWarnings("unchecked")
			List<ServiceReference<ManagedService>> refs = temp;
			Collections.sort(refs, Collections.reverseOrder());
			return refs;
		}
	}

	private void asynchUpdated(final ManagedService service, final Dictionary<String, ?> properties) {
		queue.put(new Runnable() {
			@Override
			public void run() {
				try {
					service.updated(properties);
				} catch (ConfigurationException e) {
					// we might consider doing more for ConfigurationExceptions
					Throwable cause = e.getCause();
					configurationAdminFactory.log(LogService.LOG_ERROR, e.getMessage(), cause != null ? cause : e);
				} catch (Throwable t) {
					configurationAdminFactory.log(LogService.LOG_ERROR, t.getMessage(), t);
				}
			}
		});
	}
}