package com.intellicare.shaleNShark.action.workflow;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.servlet.http.HttpSession;

import org.apache.myfaces.custom.datascroller.ScrollerActionEvent;
import org.apache.shale.util.Messages;
import org.apache.shale.view.AbstractViewController;
import org.enhydra.shark.api.client.wfbase.BaseException;
import org.enhydra.shark.api.client.wfmodel.WfAssignment;

import com.intellicare.asterisk.Agent;
import com.intellicare.logic.WorkListLogic;
import com.intellicare.shaleNShark.action.assessment.AssessmentManager;
import com.intellicare.shaleNShark.util.Constants;
import com.intellicare.shaleNShark.util.IntellicareShaleConstants;
import com.intellicare.shaleNShark.util.ShaleAssignment;
import com.intellicare.shaleNShark.util.SharkInitializer;

public class WorkListManagerBean extends AbstractViewController implements
		Serializable {

	private static final Messages messages = new Messages(
			"com.intellicare.shaleNShark.view.Bundle");

//	NOTE: getAssignments() returns assignmentsModel NOT assignments below:
	private WfAssignment[] assignments;
	
	private ShaleAssignment[] shaleAssignmentsAsArray;

	private List _assignments;

	//NOTE: getAssignments() returns assignmentsModel below:
	private DataModel assignmentsModel = new ListDataModel();

	private ShaleAssignment assignment;

	private String processKey;

	private boolean doPrerender = false;

	/************************************************************************/
	/*adding methods to get sorting:*/
	/************************************************************************/
	private String _sort;

	private boolean _ascending;

	public WorkListManagerBean() {
		_sort = "name";
		_ascending = isDefaultAscending("name");
	}

	public WorkListManagerBean(String defaultSortColumn) {
		_sort = defaultSortColumn;
		_ascending = isDefaultAscending(defaultSortColumn);
	}

	protected boolean isDefaultAscending(String sortColumn) {
		return true;
	}

	protected void sort(final String column, final boolean ascending) {

		Comparator comparator = new Comparator() {
			public int compare(Object o1, Object o2) {
				ShaleAssignment a1 = (ShaleAssignment) o1;
				ShaleAssignment a2 = (ShaleAssignment) o2;
				if (column == null) {
					return 0;
				}
				if (column.equals("name")) {
					try {
						return ascending ? a1.getName().compareTo(a2.getName())
								: a2.getName().compareTo(a1.getName());
					} catch (BaseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return 0;
					}
				} else if (column.equals("phoneNumber")) {
					try {
						return ascending ? a1.getPhoneNumber().compareTo(
								a2.getPhoneNumber()) : a2.getPhoneNumber()
								.compareTo(a1.getPhoneNumber());
					} catch (BaseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return 0;
					}
				} else if (column.equals("state")) {
					try {
						return ascending ? a1.getState().compareTo(
								a2.getState()) : a2.getState().compareTo(
								a1.getState());
					} catch (BaseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return 0;
					}
				} else if (column.equals("priority")) {
					try {
						return ascending ? a1.getPriority().compareTo(
								a2.getPriority()) : a2.getPriority().compareTo(
								a1.getPriority());
					} catch (BaseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return 0;
					}
				} else if (column.equals("customerId")) {
					try {
						return ascending ? a1.getCustomerId().compareTo(
								a2.getCustomerId()) : a2.getCustomerId()
								.compareTo(a1.getCustomerId());
					} catch (BaseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return 0;
					}
				} else if (column.equals("sceduledDate")) {
					try {
						return ascending ? a1.getScheduledDate().compareTo(
								a2.getScheduledDate()) : a2.getScheduledDate()
								.compareTo(a1.getScheduledDate());
					} catch (BaseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return 0;
					}
				}
				return 0;
			}
		};
		Collections.sort(_assignments, comparator);
	}

	public void sort(String sortColumn) {
		if (sortColumn == null) {
			throw new IllegalArgumentException(
					"Argument sortColumn must not be null.");
		}

		if (_sort.equals(sortColumn)) {
			// current sort equals new sortColumn -> reverse sort order
			_ascending = !_ascending;
		} else {
			// sort new column in default direction
			_sort = sortColumn;
			_ascending = isDefaultAscending(_sort);
		}

		sort(_sort, _ascending);
	}

	public String getSort() {
		return _sort;
	}

	public void setSort(String sort) {
		_sort = sort;
	}

	public boolean isAscending() {
		return _ascending;
	}

	public void setAscending(boolean ascending) {
		_ascending = ascending;
	}

	/************************************************************************/
	/* end adding methods to get sorting:*/
	/************************************************************************/

	/************************************************************************/
	/*adding methods to get paging:*/
	/************************************************************************/
	
	public void scrollerAction(ActionEvent event) {
		ScrollerActionEvent scrollerEvent = (ScrollerActionEvent) event;
		FacesContext.getCurrentInstance().getExternalContext().log(
				"scrollerAction: facet: " + scrollerEvent.getScrollerfacet()
						+ ", pageindex: " + scrollerEvent.getPageIndex());
	}

	/************************************************************************/
	/*adding methods to get paging:*/
	/************************************************************************/

	private void setModelWorkList(String username, String password)
			throws Exception {

		// user is proeprly authenticated andsession is still alive. So:
		WorkListLogic workListLogic = new WorkListLogic(username, password);
		assignments = workListLogic.getPhoneAssignments();
		int aLength = assignments.length;
		if ((assignments == null) || (aLength == 0)) {
			//do nothing..
		} else {
			shaleAssignmentsAsArray = new ShaleAssignment[aLength];
			
			for (int i = 0; i < aLength; i++) {
				shaleAssignmentsAsArray[i] = new ShaleAssignment(assignments[i]);
			}
			_assignments = Arrays.asList(shaleAssignmentsAsArray);
			
			// have to sort now I think..?
			sort(_sort, _ascending);
			assignmentsModel.setWrappedData(_assignments);
		}
	}

	public String getWorkList() {// ought to be renamed: getPhoneList()
		
		try {
			String username = (String) FacesContext.getCurrentInstance()
					.getExternalContext().getSessionMap()
					.get(Constants.userKey);
			String password = (String) FacesContext.getCurrentInstance()
					.getExternalContext().getSessionMap().get(Constants.pwKey);

			if ((username == null) || (password == null))
				return "loggedOff";
			setModelWorkList(username, password);
			return "workListA";
		} catch (Exception e) {
			error(messages.getMessage("workList.incorrect") + ": "
					+ e.toString());
			return "worklistException";
		}
	}

	public String getSurvey() throws BaseException {
		this.assignment = (ShaleAssignment) assignmentsModel.getRowData();
		return "survey";
	}

	public String acceptDanglingAssignment() {
		return acceptPhoneAssignment(true);
	}

	public String acceptPhoneAssignment() {
		return acceptPhoneAssignment(false);
	}

	public String acceptPhoneAssignment(boolean isDangling) {

		try {
			String username = (String) FacesContext.getCurrentInstance()
					.getExternalContext().getSessionMap()
					.get(Constants.userKey);
			String password = (String) FacesContext.getCurrentInstance()
					.getExternalContext().getSessionMap().get(Constants.pwKey);
			if ((username == null) || (password == null))
				return "loggedOff";

			HttpSession session = (HttpSession) FacesContext
					.getCurrentInstance().getExternalContext()
					.getSession(false);
			if (session == null) {
				return "loggedOff";
			}
			
			int rowCount = assignmentsModel.getRowCount();
			int rowIndex = assignmentsModel.getRowIndex();
			Object o = assignmentsModel.getWrappedData();

			this.assignment = (ShaleAssignment) assignmentsModel.getRowData();
			WorkListLogic workListLogic = new WorkListLogic(username, password);

			String sessionId = session.getId();
			Agent agent = new Agent("Geeta", "ZAP/g1/2532109", "from-internal");
			workListLogic.acceptPhoneAssignment(this.assignment
					.getActivityKey(), sessionId, agent, isDangling);

			String daoFactoryType = FacesContext.getCurrentInstance()
					.getExternalContext().getInitParameter(
							Constants.SHARK_DAO_FACTORY_TYPE);

			// workListLogic.persistSessionData(username, password, sessionId,
			// daoFactoryType);

			this.processKey = this.assignment.getProcessKey();
			workListLogic.persistSessionData(username, password, sessionId,
					daoFactoryType);

			doPrerender = true;
			if (isDangling)
				return "danglingAssessment";
			else
				return "assessment1";

		} catch (Exception e) {
			e.printStackTrace();
			error(messages.getMessage("workList.incorrect") + ": "
					+ e.toString());
			return "activityException";
		}
	}

	public DataModel getAssignments() {
		return assignmentsModel;
	}

	public void prerender() {
		
		try {
			if (doPrerender) {
				AssessmentManager assessmentBean = (AssessmentManager) getBean(IntellicareShaleConstants.ASSESSMENT_BEAN_NAME);
				assessmentBean.setProcessKey(this.processKey);
				assessmentBean.setActivityId(this.assignment.getActivityKey());
				assessmentBean.setPhoneNumber(this.assignment.getPhoneNumber());
				HttpSession session = (HttpSession) FacesContext
						.getCurrentInstance().getExternalContext().getSession(
								false);
				assessmentBean.setSessionId(session.getId());
				
				// get ready for next time:
				doPrerender = false;
			} else {// this is "default" - so worklst can be shown
				String username = (String) FacesContext.getCurrentInstance()
						.getExternalContext().getSessionMap().get(
								Constants.userKey);
				String password = (String) FacesContext.getCurrentInstance()
						.getExternalContext().getSessionMap().get(
								Constants.pwKey);
				try {
					setModelWorkList(username, password);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (BaseException e) {
			e.printStackTrace();
		}

	}

	public void preprocess() {
		SharkInitializer.initialize();
		Object workListBean = getBean("worklist");
	}

	public void init() {
		//do nothing..
	}

	public void setDoPrerender(boolean doPrerender) {
		this.doPrerender = doPrerender;
	}

}
