package pt.utl.ist.fenix.client.test.load;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;

import pt.utl.ist.fenix.client.http.BaseHttpClient;
import pt.utl.ist.fenix.client.http.PropertiesManager;
import pt.utl.ist.fenix.client.test.load.User.AddLinkCondition;
import pt.utl.ist.fenix.client.util.UsernameGenerator;

public class Student extends User {

    public Student(AddLinkCondition addLinkCondition) {
	super(addLinkCondition);
    }

    public static void main(String[] args) {
	new Student(null).run();
	System.out.flush();
	System.err.flush();
	System.exit(0);
    }

    private String username = null;

    @Override
    public void run() {
	try {
	    username = UsernameGenerator.nextStudent();
	    final long start = System.currentTimeMillis();
	    String response = login(username, PropertiesManager.PASSWORD);
	    response = enterStudentsPortal();
	    response = clickOnCourseEnrolmentLink();
	    response = beginCourseEnrolmentProcess(response);
	    response = respondToDislocatedStudentsForm(response);
	    for (String nextResp = response; nextResp != null; ) {
		nextResp = unEnrolStudentInAvailableCourse(response);
		if (nextResp != null) {
		    response = nextResp;
		}
	    }
	    for (String nextResp = response; nextResp != null; ) {
		nextResp = enrolStudentInAvailableCourse(response);
		if (nextResp != null) {
		    response = nextResp;
		}
	    }
	    final long end = System.currentTimeMillis();
//	    System.out.println("Using user: " + username + " took: " + (end - start) + " ms.");
	} catch (HttpException e) {
	    System.out.println(e.getMessage());
//	    e.printStackTrace();
	} catch (IOException e) {
	    System.out.println(e.getMessage());
//	    e.printStackTrace();
	}
	baseHttpClient.releaseClient();
    }

    public String enterStudentsPortal() throws HttpException, IOException {
	return follow(PropertiesManager.CONTEXT + "/dotIstPortal.do?prefix=/student&page=/index.do");
    }

    public String clickOnCourseEnrolmentLink() throws HttpException, IOException {
	return follow(PropertiesManager.CONTEXT + "/student/warningFirst.do");
    }

    public String beginCourseEnrolmentProcess(final String previouseResponse) throws HttpException, IOException {
	final String url = "/student/dislocatedStudent.do";
        final PostMethod postMethod = baseHttpClient.createPostMethod(url);
        BaseHttpClient.addHiddenInputsForFormFromResponse(postMethod, url, previouseResponse);
        return baseHttpClient.queryHost(postMethod);
    }

    public String respondToDislocatedStudentsForm(final String previouseResponse) throws HttpException, IOException {
	final String url = "/student/dislocatedStudent.do";
	if (previouseResponse.indexOf(url) == -1) {
	    return previouseResponse;
	}

        final PostMethod postMethod = baseHttpClient.createPostMethod(url);
        BaseHttpClient.addHiddenInputsForFormFromResponse(postMethod, url, previouseResponse);
        postMethod.addParameter("countryID", "61");
        postMethod.addParameter("dislocatedAnswer", "false");
        
        return respondToDataAuthorizationForm(baseHttpClient.queryHost(postMethod));
    }

    public String respondToDataAuthorizationForm(final String previouseResponse) throws HttpException, IOException {
	final String url = "/student/studentPersonalDataAuthorization.do";
        final PostMethod postMethod = baseHttpClient.createPostMethod(url);
        BaseHttpClient.addHiddenInputsForFormFromResponse(postMethod, url, previouseResponse);
        postMethod.addParameter("method", "registerPersonalDataInquiryAnswer");
        postMethod.addParameter("authorizationAnswer", "NO_END");
        return baseHttpClient.queryHost(postMethod);
    }

    Set<String> enroledCurricularCourseIDs = new HashSet<String>();

    private String enrolmentActionStudentInAvailableCourse(final String previouseResponse, final String method, final String idPrefix)
    		throws HttpException, IOException {
	final String url = "/student/curricularCoursesEnrollment.do";
        final PostMethod postMethod = baseHttpClient.createPostMethod(url);
        BaseHttpClient.addHiddenInputsForFormFromResponse(postMethod, url, previouseResponse);
        postMethod.removeParameter("method");
        postMethod.removeParameter("curricularCourse");
        postMethod.removeParameter("courseType");	
        final String curricularCourseID = curricularCourseID(previouseResponse, idPrefix, 0);
        if (curricularCourseID == null) {
            return null;
        }
        postMethod.addParameter("method", method);
        postMethod.addParameter("curricularCourse", curricularCourseID);
        enroledCurricularCourseIDs.add(curricularCourseID);
        postMethod.addParameter("courseType", "1");
        return baseHttpClient.queryHost(postMethod);
    }

    private static final String UnenrolInCurricularCourseIdPrefix = "value=\"Anular\" onclick=\"this.form.method.value='unenrollFromCurricularCourse'; this.form.curricularCourse.value='";
    public String unEnrolStudentInAvailableCourse(final String previouseResponse) throws HttpException, IOException {
//	System.out.println("Un-enroling... " + username);
	final String method = "unenrollFromCurricularCourse";
	return enrolmentActionStudentInAvailableCourse(previouseResponse, method, UnenrolInCurricularCourseIdPrefix);
    }

    private static final String EnrolInCurricularCourseIdPrefix = "value=\"Inscrever\" onclick=\"this.form.method.value='enrollInCurricularCourse';  this.form.curricularCourse.value='";
    public String enrolStudentInAvailableCourse(final String previouseResponse) throws HttpException, IOException {
//	System.out.println("Enroling... " + username);
	final String method = "enrollInCurricularCourse";
	return enrolmentActionStudentInAvailableCourse(previouseResponse, method, EnrolInCurricularCourseIdPrefix);
    }

    private String curricularCourseID(final String response, final String idPrefix, final int offset) {
//	if (offset > 0) System.out.println("Enrolment did not work... skipping to next course.");
	final int length = idPrefix.length();
	final int startIndex = response.indexOf(idPrefix, offset);
	final int endIndex = response.indexOf("'; ", startIndex + length + 1);
	final String nextAvailableCurricularCourseID = startIndex > 0 && endIndex > startIndex + length ? response.substring(startIndex + length, endIndex) : null;
	return enroledCurricularCourseIDs.contains(nextAvailableCurricularCourseID) ?
		curricularCourseID(response, idPrefix, endIndex) : nextAvailableCurricularCourseID;
    }

}
