package de.hsadmin.jscli;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Console;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Properties;

import javax.net.ssl.HttpsURLConnection;

public class CASTicket {

	private static final String LOGIN_URL = "https://login.hostsharing.net:443/cas/v1/tickets";
	private static final String BACKEND_URL = "https://admin.hostsharing.net:443/hsar/backend";

	private String loginURL;
	private String backendURL;
	private String grantingTicket;
	private String runAs;
	private String user;

	public CASTicket(String user, String runAs) throws JSCliException {
		this.user = user;
		this.runAs = runAs;
		Config config = Config.getInstance();
		backendURL = config.getProperty("backendURL", BACKEND_URL);
		loginURL = config.getProperty("loginURL", LOGIN_URL);
		if ("TestUmgebung".equals(loginURL)) {
			grantingTicket = "ticket:" + user;
		} else {
			grantingTicket = readFiledGrantingTicket();
		}
	}
	
	public String getTicket() throws JSCliException {
		if (grantingTicket != null && grantingTicket.startsWith("ticket:")) {
			return grantingTicket.replaceFirst("ticket", "user");
		}
		try {
			String encodedParams = URLEncoder.encode("service", "UTF-8")
					+ "=" + URLEncoder.encode(backendURL, "UTF-8");
				return doHttpPost(grantingTicket, encodedParams);
		} catch (UnsupportedEncodingException e) {
			throw new JSCliException(e);
		}
	}

	public String getRunAs() {
		return runAs;
	}

	private String getGrantingTicket() throws JSCliException {
		grantingTicket = null;
		String password = Config.getInstance().getProperty(user + ".passWord");
		if (password == null || password.length() <= 0) {
			password = readPasswordFromConsole();
		}
		try {
			String encodedParams = URLEncoder.encode("username", "UTF-8")
					+ "=" + URLEncoder.encode(user, "UTF-8")
					+ "&" + URLEncoder.encode("password", "UTF-8")
					+ "=" + URLEncoder.encode(password, "UTF-8");
			grantingTicket = doHttpPost(loginURL, encodedParams);		
		} catch (UnsupportedEncodingException e) {
			throw new JSCliException(e);
		}
		return grantingTicket;
	}

	private String readPasswordFromConsole() throws JSCliException {
		char[] password = null;
		Console console = System.console();
		if (console == null) {
			throw new JSCliException("fatal error: console not found");
		}
		password = console.readPassword("password:");
		if (password == null || password.length <= 0) {
			throw new JSCliException("no password given");
		}
		return new String(password);
	}

	private String doHttpPost(String urlString, String encodedParams) throws JSCliException {
		String result = null;
		try {
			URL url = new URL(urlString);
			HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
			connection.setRequestMethod("POST");
			connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setUseCaches(false);
			connection.setAllowUserInteraction(false);
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
			writer.write(encodedParams);
			writer.close();
			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String ticket = reader.readLine();
			String readLine = null;
			do {
				readLine = reader.readLine();
			} while (readLine != null);
			result = connection.getHeaderField("Location");
			if (ticket != null && ticket.startsWith("ST-")) {
				result = ticket;
			}
		} catch (FileNotFoundException e) {
			grantingTicket = getGrantingTicket();
			writeFiledGrantingTicket(grantingTicket);
			return getTicket();
		} catch (IOException e) {
			throw new JSCliException(e);
		}
		return result;
	}

	private String readFiledGrantingTicket() throws JSCliException {
		String filedTicket = null;
		String userHome = System.getProperty("user.home");
		String ticketFileName = userHome + "/.hsadmin.tgt";
		File file = new File(ticketFileName);
		if (file.isFile() && file.canRead()) {
			Properties properties = new Properties();
			try {
				properties.load(new FileReader(file));
				filedTicket = properties.getProperty(user);
			} catch (IOException e) {
				throw new JSCliException(e);
			}
		}
		if (filedTicket == null) {
			filedTicket = getGrantingTicket();
		}
		return filedTicket;
	}

	private void writeFiledGrantingTicket(String ticket) throws JSCliException {
		String userHome = System.getProperty("user.home");
		String ticketFileName = userHome + "/.hsadmin.tgt";
		File file = new File(ticketFileName);
		if (file.isFile() && file.canWrite()) {
			Properties properties = new Properties();
			try {
				properties.load(new FileReader(file));
				properties.put(user, ticket);
				properties.store(new FileWriter(file), "hsscript");
			} catch (IOException e) {
				throw new JSCliException(e);
			}
		}
	}

	@Override
	public String toString() {
		return grantingTicket;
	}
	
}
