package com.siemens.nkg.ejb.service.impl;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;

import org.apache.log4j.Logger;

import com.siemens.nkg.ejb.domain.DpcPostcode;
import com.siemens.nkg.ejb.service.MIServiceFacade;

@Stateless(name = "MIService")
@Remote(MIServiceFacade.class)
public class MIServiceFacadeImpl implements MIServiceFacade {

  /** Resource bundle name. */
  public static final String BUNDLE_NAME = "com.siemens.nkg.ejb.resources.MIResources";

  /** The log4j logger. */
  private static final Logger LOGGER = Logger.getLogger(MIServiceFacadeImpl.class);

  /** The entity manager for database access. */
  @PersistenceContext(unitName = "mcs", type = PersistenceContextType.TRANSACTION)
  private EntityManager entityManager;

  /**
   * Constructor.
   */
  public MIServiceFacadeImpl() {

  }

  /**
   * Gets the manual induction dialog resources depending on the chosen locale.
   * 
   * @param locale
   * @return HashMap<String, String>
   */
  @Override
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public HashMap<String, String> getResources(Locale locale) {
    HashMap<String, String> resources = new HashMap<String, String>();
    ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
    Enumeration<String> e = bundle.getKeys();

    while (e.hasMoreElements()) {
      String key = (String) e.nextElement();
      resources.put(key, bundle.getString(key));
    }

    return resources;
  }

  /**
   * Gets the post code
   * 
   * @return List<String>
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public List<String> getPostcodes() {
    Query q = this.entityManager.createNamedQuery("findPostcodes");

    List<String> postcodes = q.getResultList();

    LOGGER.debug("loaded digit postcodes: " + postcodes.size());

    return postcodes;
  }

  /**
   * Gets the post codes as entities.
   * 
   * @return List<String>
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public List<DpcPostcode> getPostcodeEntities(int firstResult, int maxResults) {
    Query q = this.entityManager.createQuery("FROM DpcPostcode");

    q.setFirstResult(firstResult);
    q.setMaxResults(maxResults);

    List<DpcPostcode> postcodes = q.getResultList();

    return postcodes;
  }

  /**
   * Gets the destination codes (destination code and city name).
   * 
   * @return HashMap<String, String>
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public HashMap<String, String> getDestinationCodes() {
    HashMap<String, String> destinationCodes = new HashMap<String, String>();

    Query q = this.entityManager.createNamedQuery("findDestinationCodes");

    List<Object[]> result = q.getResultList();

    LOGGER.debug("loaded destination codes (city names): " + result.size());

    for (Object[] objects : result) {
      destinationCodes.put((String) objects[0], (String) objects[1]);
    }

    return destinationCodes;
  }

  /**
   * Gets the 2-6 digits destination codes.
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public List<String> getDestinations() {
    Query q = this.entityManager.createNamedQuery("findDestinations");

    List<String> destinations = q.getResultList();

    LOGGER.debug("loaded 2-6 digit destination codes: " + destinations.size());

    return destinations;
  }

  /**
   * Gets the post codes reload interval in seconds
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public int getPostcodesReloadInterval() {
    int reloadInterval = 0;

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "CHECK_POSTCOD_VERSION_INTERVAL");

    List<Object> result = q.getResultList();

    reloadInterval = Integer.valueOf((String) result.get(0));

    LOGGER.debug("loaded postcodes reload interval: " + reloadInterval + "s");

    return reloadInterval;
  }

  /**
   * Gets the destination codes reload interval in seconds.
   * 
   * @return int
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public int getDestinationsReloadInterval() {
    int reloadInterval = 0;

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "CHECK_DEST_VERSION_INTERVAL");

    List<Object> result = q.getResultList();

    reloadInterval = Integer.valueOf((String) result.get(0));

    LOGGER.debug("loaded destinationcodes reload interval: " + reloadInterval + "s");

    return reloadInterval;
  }

  /**
   * Gets the version of the post code list of the server.
   * 
   * @author zhuxiaoj
   * @return String
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public String getPostcodesServerVersion() {
    String serverVersion = "";

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "POSTCODE_VERSION");

    List<Object> result = q.getResultList();

    serverVersion = (String) result.get(0);

    LOGGER.debug("loaded postcodes server version: " + serverVersion);

    return serverVersion;
  }

  /**
   * Gets the version of the destination code list of the server.
   * 
   * @return String
   */
  @Override
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public String getDestinationsServerVersion() {
    String serverVersion = "";

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "DESTINATION_VERSION");

    List<Object> result = q.getResultList();

    serverVersion = (String) result.get(0);

    LOGGER.debug("loaded destinationcodes server version: " + serverVersion);

    return serverVersion;
  }

  /**
   * Gets the server port for the communication cient.
   * 
   * @return int
   */
  @SuppressWarnings("unchecked")
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  public int getCommunicationClientServerPort() {
    int serverPort = 0;

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "COMMCLIENT_SERVER_PORT");

    List<Object> result = q.getResultList();

    serverPort = Integer.valueOf((String) result.get(0));

    LOGGER.debug("loaded server port: " + serverPort);

    return serverPort;
  }

  /**
   * Returns true if the worker is granted else false.
   * 
   * @param workerID
   * @param password
   * @return boolean
   */
  @Override
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  @SuppressWarnings("unchecked")
  public boolean isWorkerGranted(short workerID, String password) {
    boolean isGranted = false;

    Query q = this.entityManager.createNamedQuery("isWorkerGranted");

    q.setParameter("workerID", workerID);
    q.setParameter("password", password);

    List<Object> result = q.getResultList();

    if (result != null) {
      if (result.size() > 0) {
        isGranted = true;
      }
    }

    LOGGER.debug("worker " + workerID + " is granted state: " + isGranted);

    return isGranted;
  }

  /**
   * Gets the name of a worker with the specified ID.
   * 
   * @param workerID
   * @return String
   */
  @Override
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  @SuppressWarnings("unchecked")
  public String getWorkerName(short workerID) {
    String workerName = "";

    Query q = this.entityManager.createNamedQuery("findWorkerName");

    q.setParameter("workerID", workerID);

    List<Object> result = q.getResultList();

    if (result != null) {
      if (result.size() > 0) {
        workerName = (String) result.get(0);
      }
    }

    return workerName;
  }

  /**
   * Gets the read timeout (in ms) for the communication client socket.
   * 
   * @return int
   */
  @Override
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  @SuppressWarnings("unchecked")
  public int getCommunicationClientSocketTimeout() {
    int socketTimeout = 0;

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "COMMCLIENT_SOCKET_TIMEOUT");

    List<Object> result = q.getResultList();

    socketTimeout = Integer.valueOf((String) result.get(0));

    LOGGER.debug("loaded communication client socket timeout: " + socketTimeout + "ms");

    return socketTimeout;
  }

  /**
   * Gets the communication client thread timeout (in ms).
   * 
   * @return int
   */
  @Override
  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  @SuppressWarnings("unchecked")
  public int getCommunicationClientThreadTimeout() {
    int threadTimeout = 0;

    Query q = this.entityManager.createNamedQuery("getParameterValue");

    q.setParameter("paramName", "COMMCLIENT_THREAD_TIMEOUT");

    List<Object> result = q.getResultList();

    threadTimeout = Integer.valueOf((String) result.get(0));

    LOGGER.debug("loaded communication client thread timeout: " + threadTimeout + "ms");

    return threadTimeout;
  }
}
