package de.hsadmin.core.model.onetier;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import de.hsadmin.core.model.AuthenticationException;

public class TicketValidator {

	private static final Log log = LogFactory.getLog(TicketValidator.class);

	private static TicketValidator instance;
	
	private String proxyValidateURL;
	private String proxyServiceURL;
	
	private TicketValidator() {
		proxyServiceURL = null;
		proxyValidateURL = null;
	}
	
	public static TicketValidator getInstance() {
		if (instance == null) {
			instance = new TicketValidator();
		}
		return instance;
	}
	
	public void initialize(String validateURL, String serviceURL) {
		proxyServiceURL = serviceURL;
		proxyValidateURL = validateURL;
	}
	
	public boolean validateTicket(String runAsUser, String ticket) throws AuthenticationException {
		String ticketUser = validateTicket(ticket);
		if (runAsUser != null && 
				(runAsUser.equals(ticketUser)		// user himself
					|| (ticketUser.length() == 5 && runAsUser.startsWith(ticketUser))
													// pac-admin
					|| (ticketUser.length() == 3 && runAsUser.startsWith(ticketUser))
													// member
					|| ticketUser.length() == 2)	// hostmaster
					// TODO: add test for member-account
				) {
			return true;
		} else {
			throw new AuthenticationException("User " + ticketUser + " is not allowed to run as " + runAsUser);
		}
	}

	private String validateTicket(String ticket) throws AuthenticationException {
		if (proxyServiceURL == null || proxyServiceURL == null) {
			log.fatal("TicketValidator is not initialized.");
			throw new RuntimeException("TicketValidator is not initialized.");
		}
		try {
			URL url = new URL(proxyValidateURL + "?service=" + proxyServiceURL + "&ticket=" + ticket);
			URLConnection httpConnection = url.openConnection();
			httpConnection.connect();
			InputStream inputStream = httpConnection.getInputStream();
			BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
			String nextLine = reader.readLine();  
			while (nextLine != null) {
				if (nextLine.contains("<cas:user>")) {
					String user = extractUser(nextLine);
					inputStream.close();
					return user;
				}
				nextLine = reader.readLine();
			}
			inputStream.close();
			log.debug("Ticket validation failed: " + ticket);
			throw new AuthenticationException("Invalid Ticket: " + ticket);
		} catch (MalformedURLException e) {
			log.fatal(e);
			throw new AuthenticationException(e.getMessage());
		} catch (IOException e) {
			log.fatal(e);
			throw new AuthenticationException(e.getMessage());
		}
	}

	private String extractUser(String nextLine) {
		int start = nextLine.indexOf("<cas:user>");
		int end = nextLine.indexOf("</cas:user>");
		String user = nextLine.substring(start + 10, end);
		return user;
	}

}
