package ve.gob.cnti.bonita;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.impl.conn.SchemeRegistryFactory;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;

import ve.gob.cnti.receiver.utils.PropertiesReader;



/**TODO Cambiar la accesibilidad de los metodos y atributos de esta clase
 * 
 * @author usuario
 *
 */
public class SessionImpl implements ISession{
	
	PropertiesReader pr = new PropertiesReader("/home/emendez/Servidores/jboss-eap-6.3/standalone/configuration/receiverEJB","eee");
	
	public HttpClient httpClient;
	

	public void setHttpClient(HttpClient httpClient) {
		this.httpClient = httpClient;
	}

	private HttpContext httpContext;
	private String bonitaURI = pr.getProperty("BONITA_REST_URL");
	public String response;
	

	/** TODO
	 * 
	 * Conexion a bonita mediante servicios rest
	 */
	public static PoolingClientConnectionManager getConnectionManager() {
		PoolingClientConnectionManager conMan = new PoolingClientConnectionManager(SchemeRegistryFactory.createDefault());
		conMan.setMaxTotal(200);
		conMan.setDefaultMaxPerRoute(200);
		return conMan;
	}
	
	public HttpResponse executeGetRequest(String apiURI) {
		try {
			System.out.println(bonitaURI + apiURI);
			HttpGet getRequest = new HttpGet(bonitaURI + apiURI);
			
			HttpResponse response = httpClient.execute(getRequest, httpContext);
			return response;

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}
	
	public void loginAs(String username, String password) {

		try {

			CookieStore cookieStore = new BasicCookieStore();
			httpContext = new BasicHttpContext();
			httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

			String loginURL = "/loginservice";

			// If you misspell a parameter you will get a HTTP 500 error
			List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
			urlParameters.add(new BasicNameValuePair("username", username));
			urlParameters.add(new BasicNameValuePair("password", password));
			urlParameters.add(new BasicNameValuePair("redirect", "false"));

			// UTF-8 is mandatory otherwise you get a NPE
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(urlParameters, "utf-8");
			executePostRequest(loginURL, entity);

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}
	
	public void logout() {
		consumeResponse(executeGetRequest("/logoutservice"),false);
	}
			
	private int executePostRequest(String apiURI, UrlEncodedFormEntity entity) {
		try {
			HttpPost postRequest = new HttpPost(bonitaURI + apiURI);

			postRequest.setEntity(entity);

			HttpResponse response = httpClient.execute(postRequest, httpContext);

			return consumeResponse(response, true);

		} catch (HttpHostConnectException e) {
			throw new RuntimeException("Bonita bundle may not have been started, or the URL is invalid. Please verify hostname and port number. URL used is: " + bonitaURI,e);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}
	
	public HttpResponse executePostRequest(String apiURI, String payloadAsString) {
		try {
			HttpPost postRequest = new HttpPost(bonitaURI + apiURI);

			StringEntity input = new StringEntity(payloadAsString);
			input.setContentType("application/json");

			postRequest.setEntity(input);

			HttpResponse response = httpClient.execute(postRequest, httpContext);

			return response;

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	public HttpResponse executePutRequest(String apiURI, String payloadAsString) {
		try {
			HttpPut putRequest = new HttpPut(bonitaURI + apiURI);
			putRequest.addHeader("Content-Type", "application/json");
			StringEntity input = new StringEntity(payloadAsString);
			input.setContentType("application/json");
			putRequest.setEntity(input);
			return httpClient.execute(putRequest, httpContext);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	
	/**TODO
	 * 
	 * Implementar una forma de consumir la respuesta en un bean
	 * 
	 * @param response
	 * @param printResponse
	 * @return
	 */
	public int consumeResponse(HttpResponse response, boolean printResponse) {

		String responseAsString = consumeResponseIfNecessary(response);
		if(printResponse) {			
			this.response = responseAsString;
		
		}
		

		return ensureStatusOk(response);
	}

	public String consumeResponseIfNecessary(HttpResponse response) {
		if (response.getEntity() != null) {
			BufferedReader rd;
			try {
				rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

				StringBuffer result = new StringBuffer();
				String line = "";
				while ((line = rd.readLine()) != null) {
					result.append(line);
				}
				return result.toString();
			} catch (Exception e) {
				throw new RuntimeException("Failed to consume response.", e);
			}
		} else {
			return "";
		}
	}
	
	private int ensureStatusOk(HttpResponse response) {
		if (response.getStatusLine().getStatusCode() != 201 && response.getStatusLine().getStatusCode() != 200) {
			throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode() + " : "
					+ response.getStatusLine().getReasonPhrase());
		}
		return response.getStatusLine().getStatusCode();
	}
	
	public void makeSureLocaleIsActive() {
		consumeResponse(executeGetRequest("/API/system/i18ntranslation?f=locale%3den"), false);
	}
	
	
	/**
	 * Autenticación de usuarios para pruebas
	 */
	public void loginAsAdmin() {
		loginAs("admin", "admin");
	}
	
	
	/**
	 * Inicia la sesion y prepara el gestos de peticiones
	 * @param user
	 * @param pass
	 */
	public void startConection(String user, String pass){
		
		PoolingClientConnectionManager conMan = SessionImpl.getConnectionManager();
		this.setHttpClient(new DefaultHttpClient(conMan));
		this.loginAs(user, pass);
		this.makeSureLocaleIsActive();
		
	}
	
	
	/**
	 * Cierra la Conexion y desloguea al usuario
	 */
	public void stopConection(){
		
		this.logout();
		this.httpClient.getConnectionManager().shutdown();
		
	}

	

	
}
