/*
 * Copyright (c) 2016 Gigatronik Ingolstadt GmbH and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.eclipse.mdm.api.odsadapter;

import java.util.Map;

import org.asam.ods.AoException;
import org.asam.ods.AoFactory;
import org.asam.ods.AoFactoryHelper;
import org.asam.ods.AoSession;
import org.eclipse.mdm.api.base.ConnectionException;
import org.eclipse.mdm.api.dflt.ApplicationContext;
import org.eclipse.mdm.api.dflt.ApplicationContextFactory;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.InvalidName;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.highqsoft.corbafileserver.generated.CORBAFileServerIF;
import com.highqsoft.corbafileserver.generated.CORBAFileServerIFHelper;

/**
 * ASAM ODS implementation of the {@link ApplicationContextFactory} interface.
 *
 * @since 1.0.0
 * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
 */
public class ODSContextFactory implements ApplicationContextFactory {

	// ======================================================================
	// Class variables
	// ======================================================================

	public static final String PARAM_NAMESERVICE = "nameservice";

	public static final String PARAM_SERVICENAME = "servicename";

	public static final String PARAM_USER = "user";

	public static final String PARAM_PASSWORD = "password";

	public static final String PARAM_ELASTIC_SEARCH_URL = "elasticsearch.url";

	private static final String AUTH_TEMPLATE = "USER=%s,PASSWORD=%s,CREATE_COSESSION_ALLOWED=TRUE";

	private static final Logger LOGGER = LoggerFactory.getLogger(ODSContextFactory.class);

	// ======================================================================
	// Instance variables
	// ======================================================================

	private final ORB orb = ORB.init(new String[] {}, System.getProperties());

	// ======================================================================
	// Public methods
	// ======================================================================

	public ODSContextFactory() {
		LOGGER.debug("Default constructor called.");
	}

	/**
	 * {@inheritDoc}
	 *
	 * <p>
	 * <b>Note:</b> Given parameters {@code Map} must contain values for each of
	 * the following keys:
	 *
	 * <ul>
	 * <li>{@value #PARAM_NAMESERVICE}</li>
	 * <li>{@value #PARAM_SERVICENAME}</li>
	 * <li>{@value #PARAM_USER}</li>
	 * <li>{@value #PARAM_PASSWORD}</li>
	 * <li>{@value #PARAM_ELASTIC_SEARCH_URL}</li>
	 * </ul>
	 *
	 * Listed names are available via public fields of this class.
	 */
	@Override
	public ApplicationContext connect(Map<String, String> parameters) throws ConnectionException {
		AoSession aoSession = null;
		try (ServiceLocator serviceLocator = new ServiceLocator(orb, getParameter(parameters, PARAM_NAMESERVICE))) {
			String nameOfService = getParameter(parameters, PARAM_SERVICENAME).replace(".ASAM-ODS", "");

			AoFactory aoFactory = serviceLocator.resolveFactory(nameOfService);
			LOGGER.info("Connecting to ODS Server ...");

			LOGGER.info("AoFactory name: {}", aoFactory.getName());
			LOGGER.info("AoFactory description: {}", aoFactory.getDescription());
			LOGGER.info("AoFactory interface version: {}", aoFactory.getInterfaceVersion());
			LOGGER.info("AoFactory type: {}", aoFactory.getType());

			aoSession = aoFactory.newSession(String.format(AUTH_TEMPLATE, getParameter(parameters, PARAM_USER),
					getParameter(parameters, PARAM_PASSWORD)));
			LOGGER.info("Connection to ODS server established.");

			CORBAFileServerIF fileServer = serviceLocator.resolveFileServer(nameOfService);
			return new ODSContext(orb, aoSession, fileServer, parameters); 
		} catch (AoException e) {
			closeSession(aoSession);
			throw new ConnectionException("Unable to connect to ODS server due to: " + e.reason, e);
		}
	}

	// ======================================================================
	// Private methods
	// ======================================================================

	/**
	 * Closes given {@link AoSession} with catching and logging errors.
	 *
	 * @param aoSession
	 *            The {@code AoSession} that shall be closed.
	 */
	private static void closeSession(AoSession aoSession) {
		if (aoSession == null) {
			return;
		}

		try {
			aoSession.close();
		} catch (AoException e) {
			LOGGER.warn("Unable to close sesssion due to: " + e.reason, e);
		}
	}

	/**
	 * Reads the property identified by given property name.
	 *
	 * @param parameters
	 *            The properties {@code Map}.
	 * @param name
	 *            The property name.
	 * @return The property value is returned.
	 * @throws ConnectionException
	 *             Thrown if property does not exist or is empty.
	 */
	private static String getParameter(Map<String, String> parameters, String name) throws ConnectionException {
		String value = parameters.get(name);
		if (value == null || value.isEmpty()) {
			throw new ConnectionException("Connection parameter with name '" + name + "' is either missing or empty.");
		}

		return value;
	}

	// ======================================================================
	// Inner classes
	// ======================================================================

	/**
	 * Used to resolve CORBA service object by ID and kind.
	 */
	private static final class ServiceLocator implements AutoCloseable {

		// ======================================================================
		// Instance variables
		// ======================================================================

		private NamingContextExt namingContext;

		// ======================================================================
		// Constructors
		// ======================================================================

		/**
		 * Constructor.
		 *
		 * @param orb
		 *            The {@link ORB} singleton instance.
		 * @param path
		 *            The naming context path.
		 * @throws ConnectionException
		 *             Thrown if unable to resolve the naming context.
		 */
		public ServiceLocator(ORB orb, String path) throws ConnectionException {
			namingContext = NamingContextExtHelper.narrow(orb.string_to_object(path));
			if (namingContext == null) {
				throw new ConnectionException("Unable to resolve NameService '" + path + "'.");
			}
		}

		// ======================================================================
		// Public methods
		// ======================================================================

		/**
		 * Resolves and returns the {@link AoFactory} service for given ID.
		 *
		 * @param id
		 *            Used as identifier.
		 * @return The {@code AoFactory} is returned.
		 * @throws ConnectionException
		 *             Thrown if unable to resolve the {@code
		 * 		AoFactory}.
		 */
		public AoFactory resolveFactory(String id) throws ConnectionException {
			return AoFactoryHelper.narrow(resolve(id, "ASAM-ODS"));
		}

		/**
		 * Resolves and returns the {@link CORBAFileServerIF} service for given
		 * ID.
		 *
		 * @param id
		 *            Used as identifier.
		 * @return The {@code CORBAFileServerIF} or null, if none found, is
		 *         returned.
		 */
		public CORBAFileServerIF resolveFileServer(String id) {
			try {
				return CORBAFileServerIFHelper.narrow(resolve(id, "CORBA-FT"));
			} catch (ConnectionException e) {
				LOGGER.warn(e.getMessage());
				return null;
			}
		}

		/**
		 * Resolves a CORBA service object for given id and kind.
		 *
		 * @param id
		 *            Used as identifier.
		 * @param kind
		 *            Used as qualifier.
		 * @return The resolved CORBA service object is returned.
		 * @throws ConnectionException
		 *             Thrown in case of errors.
		 */
		public Object resolve(String id, String kind) throws ConnectionException {
			try {
				return namingContext.resolve(new NameComponent[] { new NameComponent(id, kind) });
			} catch (NotFound | CannotProceed | InvalidName e) {
				throw new ConnectionException("Unable to resolve service '" + id + "." + kind + "'.", e);
			}
		}

		@Override
		public void close() throws ConnectionException {
			namingContext._release();
		}

	}

}
