/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.testing.wikifood.mdb;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

import lu.tudor.santec.gecamed.patient.utils.PatientUpdateObject;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;


@MessageDriven(activationConfig =
{
  @ActivationConfigProperty(propertyName = "destinationType", 	propertyValue="javax.jms.Topic"),
  @ActivationConfigProperty(propertyName = "destination",		propertyValue=WikifoodAllergyImporterBean.TOPIC_NAME),
  @ActivationConfigProperty(propertyName = "acknowledgeMode", 	propertyValue = "AUTO_ACKNOWLEDGE"),
  @ActivationConfigProperty(propertyName = "maxSession", 		propertyValue = "1")
 })
public class WikifoodAllergyImporterBean implements MessageListener{

	/**
	 * The file where the properties are stored
	 */
	public static final String PROPERTY_FILE = "WikifoodAllergyImporter.properties";
	
	/**
	 * The dir of the config files
	 */
	public static final String CONFIG_URI 	 = System.getProperty("jboss.server.config.url").replaceAll(" ", "%20");
	
	/**
	 * the name of the Topic to describe to. this MessageTopic has to exist in
	 * the JBoss configuration
	 */
	protected static final String	TOPIC_NAME	= "topic/GeCam/patientmanagementTopic";
	
	
	protected static final String	WIKIFOOD_URL 		= "WIKIFOOD_URL";
	protected static final String	WIKIFOOD_USERNAME 	= "WIKIFOOD_USERNAME";
	protected static final String	WIKIFOOD_PASSWORD	= "WIKIFOOD_PASSWORD";
	protected static final String	GECAMED_PATID		= "GECAMED_PATID";
	    
	private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
	
    private static int instanceNr;
    
    private static boolean isrunning;
	
	/**
	 * static logger for this class
	 */
	private static Logger logger = Logger.getLogger(WikifoodAllergyImporterBean.class.getName());

	private static Properties properties;
	
	
	/* (non-Javadoc)
	 * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
	 */
	public void onMessage(Message msg) {
		/* ================================================== */
    
		// TODO DEBUG ONLY
		properties = null;
				
		
	    isrunning = true;
		try	{
			if (msg instanceof ObjectMessage) {
				Object payload = ((ObjectMessage) msg).getObject();
				if (payload instanceof PatientUpdateObject) {
					PatientUpdateObject update = (PatientUpdateObject) payload;
					System.out.println("Received PatientUpdateObject Message on "+TOPIC_NAME);
					System.out.println(payload);
					System.out.println("---------------------------------------");
					
					
					Integer patID = null;
					try {
						String patIDString = getProperty(GECAMED_PATID);
						patID = Integer.parseInt(patIDString);
					} catch (Exception e) {
						logger.warn("No Valid" + GECAMED_PATID + " configured in " + PROPERTY_FILE);
						return;
					}
					
					if (patID == null) {
						logger.warn("No " + GECAMED_PATID + " configured in " + PROPERTY_FILE);
						return;
					}
						
					if (patID.equals(update.getPatID()) && PatientUpdateObject.C_ALLERGIES.equals(update.getContext())) {
						
						System.out.println("\t Triggering Wikifood Update!");
						
						updateWikiFood(update);
						
					} else {
						logger.warn(GECAMED_PATID + " does not match ("+patID +"!="+update.getPatID()+"), exiting Wikifood Importer.");
					}
					
				}
			}
		}
		catch (Exception p_Exception){
			logger.log(Level.FATAL, "Failed to process received message",p_Exception);
		}
	     
		isrunning = false;
	     /* ================================================== */
	}
	
	private void updateWikiFood(PatientUpdateObject update) {
		try {
			String URL = getProperty(WIKIFOOD_URL);
			String USER = getProperty(WIKIFOOD_USERNAME);
			String PASS = getProperty(WIKIFOOD_PASSWORD);
			
			String content = buildXML(update);
			
			URL url = new URL(URL+"?method=setAllergyProfile&loginname=" + 
					URLEncoder.encode(USER, "UTF-8") + 
					"&password=" + PASS);
			
	        System.out.println(url.toString());
	        
	        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
	        conn.setRequestMethod("POST");
	        conn.setRequestProperty("Content-Type", "text/xml");
	        conn.setDoOutput(true);
	        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
		    wr.write(content);
		    wr.flush();
	   
	        // Get the response
	        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
	        String line;
	        StringBuffer response = new StringBuffer();
		    System.out.println("---------------------------------");
		    StringBuffer sb = new StringBuffer("Response of UploadAllergyProfile():\n");
	        while ((line = rd.readLine()) != null) {
	        	sb.append(line).append("\n");
	            response.append(line);
	        }
	        System.out.println(sb.toString());
	        System.out.println("---------------------------------");
			
//			BufferedReader in = new BufferedReader(new InputStreamReader(request.post()));
//			String inputLine;
//			while ((inputLine = in.readLine()) != null) {
//				System.out.println(inputLine);
//			}
//			in.close();
	
			logger.info("Wikifood Update Done");
		} catch (Exception e) {
			logger.warn("Error Updating Wikifood", e);
		}
		
	}

	private String buildXML(PatientUpdateObject update) throws Exception {
		StringBuffer sb = new StringBuffer();
		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append("\n");
		sb.append("<allergy_profile xmlns=\"http://www.wikifood.lu\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.wikifood.lu userfood.xsd\">").append("\n");
		sb.append("<modification>").append(df.format(new Date())).append("</modification>").append("\n");
		sb.append("<allergens>").append("\n");
		
		String desc = update.getDesc();
		String[] allergies = desc.split("\n");
		for (String allergy : allergies) {
			String[] allergyData = allergy.split("=");
			String id = allergyData[0];
			String name = allergyData[1];
			if (id != null && id.length() > 0 && ! id.equals("null")) {
				sb.append("\t<allergen id=\"").append(id).append("\"><![CDATA[").append(name).append("]]></allergen>\n");				
			}
		}

		sb.append("</allergens>").append("\n");
		sb.append("</allergy_profile>").append("\n");
		
		return sb.toString();
	}

	@PostConstruct
	public void postConstruct () {
		SSLManager.initSSL();
	    instanceNr++;
	    logger.info(getClass().getSimpleName() + " postConstruct instances: " + instanceNr);
	}
	
	
	@PreDestroy
	public void preDestroy () {
	    instanceNr--;
	    logger.info(getClass().getSimpleName() + " preDestroy instances: " + instanceNr);
	}
	
	private static void loadProperties() {
		/* ------------------------------------------------------- */
		properties = new Properties();
		try {
			File fileConfigDir = new File(new URI(CONFIG_URI));
			File fileConfigFile = new File(fileConfigDir, PROPERTY_FILE);
			properties.load(new FileInputStream(fileConfigFile));
			/* ------------------------------------------------------- */
		} catch (URISyntaxException e) {
			e.printStackTrace();
			properties = null;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			properties = null;
		} catch (IOException e) {
			e.printStackTrace();
			properties = null;
		}
		/* ------------------------------------------------------- */
	}
	
	/**
	 * Read the property from the gecamed_server.properties
	 * 
	 * @param key
	 * @return
	 */
	public static String getProperty(String key) {
		/* ================================================== */
		if (properties == null)
			loadProperties();
		if (properties.size() < 1) {
			return null;
		}
		/* ------------------------------------------------------- */
		return properties.getProperty(key);
		/* ================================================== */
	}

}