/**
 * ServiceDispatchAction.java
 * Created on Jun 25, 2008
 * (C) Copyright TANDBERG Television Ltd.
 */
package com.tandbergtv.watchpoint.pmm.web.actions.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.actions.DispatchAction;

import com.tandbergtv.watchpoint.pmm.entities.ContainerType;
import com.tandbergtv.watchpoint.pmm.entities.IContainer;
import com.tandbergtv.watchpoint.pmm.entities.Job;
import com.tandbergtv.watchpoint.pmm.entities.Partner;
import com.tandbergtv.watchpoint.pmm.entities.PartnerType;
import com.tandbergtv.watchpoint.pmm.entities.Schedule;
import com.tandbergtv.watchpoint.pmm.entities.Service;
import com.tandbergtv.watchpoint.pmm.job.IJobManager;
import com.tandbergtv.watchpoint.pmm.job.JobManager;
import com.tandbergtv.watchpoint.pmm.partner.IPartnerManagement;
import com.tandbergtv.watchpoint.pmm.partner.PartnerManager;
import com.tandbergtv.watchpoint.pmm.service.IServiceManagement;
import com.tandbergtv.watchpoint.pmm.service.ServiceManager;
import com.tandbergtv.watchpoint.pmm.util.ContextManager;
import com.tandbergtv.watchpoint.pmm.util.IContextManager;
import com.tandbergtv.watchpoint.pmm.web.formbeans.job.JobForm;
import com.tandbergtv.watchpoint.pmm.web.formbeans.job.JobListForm;
import com.tandbergtv.watchpoint.pmm.web.formbeans.service.ServiceForm;
import com.tandbergtv.watchpoint.pmm.web.formbeans.service.ServiceListForm;
import com.tandbergtv.watchpoint.pmm.web.formbeans.service.ServicePartnersListForm;
import com.tandbergtv.watchpoint.pmm.web.schedule.ScheduleForm;
import com.tandbergtv.watchpoint.pmm.web.schedule.ScheduleListForm;
import com.tandbergtv.watchpoint.pmm.web.util.CommonUtils;
import com.tandbergtv.watchpoint.pmm.web.util.GUISearchHelper;
import com.tandbergtv.watchpoint.pmm.web.util.HTMLOption;
import com.tandbergtv.watchpoint.pmm.web.util.PMMTableConfigHelper;
import com.tandbergtv.workflow.core.service.ServiceRegistry;
import com.tandbergtv.workflow.core.service.cache.ICacheService;
import com.tandbergtv.workflow.util.SearchCriteria;
import com.tandbergtv.workflow.web.common.StaticCodes;
import com.tandbergtv.workflow.web.formbeans.PaginationAndSortingForm;
import com.tandbergtv.workflow.web.util.ExportUtility;

/**
 * @author Vlada Jakobac
 * 
 */
public class ServiceDispatchAction extends DispatchAction {

	private static final String SERVICES = "services";

	private static final Logger logger = Logger
			.getLogger(ServiceDispatchAction.class);

	private static final String FORWARD_POST_CREATE_SERVICE = "postCreateService";

	private static final String FORWARD_SERVICE_DETAILS = "serviceDetails";

	private static final String JOBS = "jobs";

	private static final String SCHEDULES = "schedules";

	private static String CONTAINER_CACHE_SERVICE_NAME = "Container Cache";

	private static final String DISPLAY_MESSAGE = "service.update.messages";

	private static final String DISPLAY_ERRORS = "service.update.errors";

	private IServiceManagement serviceManager;

	public ServiceDispatchAction() {
		super();
		this.serviceManager = ServiceManager.getInstance();
	}

	public ActionForward getServicesView(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		boolean exportFlag = false;
		exportFlag = ((request.getParameter("exportData") != null) && (request
				.getParameter("exportData").toString().equals("export")))
				? true
				: false;

		ServiceListForm serviceListForm = (ServiceListForm) actionForm;
		SearchCriteria searchCriteria = serviceListForm.getSearchCriteria();

		logger.debug("The Search Criteria--->" + searchCriteria);

		List<ServiceForm> services = new ArrayList<ServiceForm>();

		if (exportFlag) {
			searchCriteria.setStartingRecordNumber(0);
			searchCriteria.setRecordsCount(Integer.MAX_VALUE);
		}
		List<Service> lsServices = serviceManager
				.getServicesBySearchCriteria(searchCriteria);
		// Iterating thru the list of services and making a collection of
		// ServiceForm objects
		ServiceForm serviceForm = null;
		for (Service service : lsServices) {
			serviceForm = new ServiceForm();
			serviceForm = prepareServiceForm(service, serviceForm);
			services.add(serviceForm);
		}

		// Get the total number of active Services
		int iTotalRecords = serviceManager.getTotalActiveServiceCount();
		
		logger.debug("Total number of records -->" + iTotalRecords);
		serviceListForm.setTotalRecords(iTotalRecords);

		// put the collection into Servicelistform
		serviceListForm.setServiceList(services);

		// Export Data to Excel
		if (exportFlag) {
			
			ExportUtility exportUtility = new ExportUtility();
			exportUtility.exportDataToExcel(request, response, serviceListForm,
					services,PMMTableConfigHelper.getTableConfigFile());
			
			return null;
		}
		// Assign to parent reference
		PaginationAndSortingForm paginationAndSortingForm = serviceListForm;

		// Search Criteria
		request.setAttribute(StaticCodes.SEARCH_CRITERIA,
				paginationAndSortingForm);

		return actionMapping.findForward(SERVICES);
	}

	/**
	 * This method populates the data from the Service Object to ServiceForm
	 * which is used for the UI presentation
	 * 
	 * @param service
	 *            Service instance
	 * @param serviceForm
	 *            ServiceForm instance
	 * @return ServiceForm instance
	 */
	private ServiceForm prepareServiceForm(Service service,
			ServiceForm serviceForm) {

		// Setting all the Service Properties into the formbean
		serviceForm.setId(String.valueOf(service.getId()));
		serviceForm.setName(service.getName());

		serviceForm.setDescription(service.getDescription());

		Set<Partner> partners = service.getPartners();
		Set<Partner> sourcePartners = new HashSet<Partner>();
		Set<Partner> distributionPartners = new HashSet<Partner>();
		for (Partner partner : partners) {
			if (partner.getType() == PartnerType.DISTRIBUTION) {
				distributionPartners.add(partner);
			} else if (partner.getType() == PartnerType.SOURCE) {
				sourcePartners.add(partner);
			}
		}
		serviceForm.setDistributionPartners(distributionPartners);
		serviceForm.setSourcePartners(sourcePartners);
		serviceForm.setPartners(service.getPartners());
		serviceForm.setContextId(service.getContext().getId());
		serviceForm.setLookupKey(service.getLookupKey());

		return serviceForm;
	}

	public ActionForward createServiceSetup(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		return actionMapping.findForward("createService");
	}

	public ActionForward createService(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		ServiceForm serviceForm = (ServiceForm) actionForm;

		Service service = new Service();

		// Prepare a Service object from the ServiceForm object
		service = prepareService(serviceForm, service);

		service = serviceManager.createService(service);
		logger.debug("new service id=" + service.getId());
		serviceForm.setId(String.valueOf(service.getId()));
		serviceForm.setContextId(service.getContainerContextId());

		// Set the attribute for the post message after creation of a
		// Service
		request.setAttribute(StaticCodes.SERVICE_CREATED,
				StaticCodes.SERVICE_CREATED);

		// Set the ServiceForm in the Request Scope
		request.setAttribute(StaticCodes.OUTPUT_DATA, serviceForm);

		return actionMapping.findForward(FORWARD_POST_CREATE_SERVICE);

	}

	private Service prepareService(ServiceForm serviceForm, Service service)
			throws Exception {

		// Setting Service properties
		service.setName(serviceForm.getName());

		service.setDescription(serviceForm.getDescription());

		service.setLookupKey(serviceForm.getLookupKey());
		IContextManager ctxMgr = ContextManager.getInstance();
		service.setContext(ctxMgr.getContext(serviceForm.getContextId()));

		return service;
	}

	@SuppressWarnings("unchecked")
	public ActionForward getServiceDetails(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		logger.debug("Starting---->");
		Long contextId = null;

		ServiceForm serviceForm = (ServiceForm) actionForm;

		contextId = serviceForm.getContextId();
		logger.debug("Service contextId------->" + contextId);
		Long serviceId = null;

		if (contextId != null && contextId != 0) {
			// obtain serviceId from contextId
			ICacheService<IContainer> containerCache = (ICacheService<IContainer>) ServiceRegistry
					.getDefault().lookup(CONTAINER_CACHE_SERVICE_NAME);
			IContainer container = containerCache.get(contextId);
			serviceId = ((Service) container).getId();
		} else if (serviceForm.getId() != null) {
			serviceId = Long.valueOf(serviceForm.getId());
		}

		logger.debug("Service Id------->" + serviceId);

		Service service = serviceManager.getService(serviceId);

		// Preparing ServiceForm Object from the Service Object
		serviceForm = prepareServiceForm(service, serviceForm);

		request.setAttribute(StaticCodes.MODIFYSERVICE_TAB_ITEM,
				StaticCodes.MODIFYSERVICE_TAB_ITEM);

		request.setAttribute(StaticCodes.OUTPUT_DATA, serviceForm);
		logger.debug("Ending---->");
		return actionMapping.findForward(FORWARD_SERVICE_DETAILS);
	}

	public ActionForward deleteServices(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		ServiceForm serviceForm = (ServiceForm) actionForm;
		String strServiceIds[] = serviceForm.getSelectedServices();

		ActionMessages messages = new ActionMessages();

		for (int i = 0; i < strServiceIds.length; i++) {
			try {
				boolean isDeleted = serviceManager.deleteService(Long
						.parseLong(strServiceIds[i]));
				if (isDeleted){
					messages.add(StaticCodes.INFO_MESSAGE, new ActionMessage(
							DISPLAY_MESSAGE, "Service [" + strServiceIds[i]
									+ "] deleted successfully."));
				} else {
					messages.add(StaticCodes.INFO_ERROR, new ActionMessage(
							DISPLAY_ERRORS, "Service [" + strServiceIds[i]
									+ "] cannot be deleted."));
				}
			} catch (Exception exception) {
				messages.add(StaticCodes.INFO_ERROR, new ActionMessage(
						DISPLAY_ERRORS, exception.getMessage()));

			}
		}

		saveErrors(request, messages);
		saveMessages(request, messages);

		return actionMapping.findForward(SERVICES);
	}

	public ActionForward updateService(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		try {
			ServiceForm serviceForm = (ServiceForm) actionForm;

			Service service = serviceManager.getService(Long
					.parseLong(serviceForm.getId()));
			
			prepareService(serviceForm, service);
			service = serviceManager.updateService(service);
			serviceForm.setId(String.valueOf(service.getId()));

			request.setAttribute(StaticCodes.SERVICE_UPDATED,
					StaticCodes.SERVICE_UPDATED);

			request.setAttribute(StaticCodes.OUTPUT_DATA, serviceForm);
		} catch (Exception validationException) {
			// to do
		}

		return actionMapping.findForward(FORWARD_POST_CREATE_SERVICE);
	}

	@SuppressWarnings("unchecked")
	public ActionForward getPartnersForService(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		ServicePartnersListForm servicePartnersLF = (ServicePartnersListForm) actionForm;
		String contextId = servicePartnersLF.getContextId();
		populatePartnersMaps(servicePartnersLF);

		ICacheService<IContainer> containerCache = (ICacheService<IContainer>) ServiceRegistry
				.getDefault().lookup(CONTAINER_CACHE_SERVICE_NAME);
		IContainer container = containerCache.get(new Long(contextId));
		ContainerType containerType = container.getContainerType();
		if (containerType == ContainerType.SERVICE) {// it must be!!!
			String serviceName = ((Service) container).getName();
			servicePartnersLF.setName(serviceName);

		}
		servicePartnersLF
				.setEntityType(container.getContainerType().toString());

		request.setAttribute(StaticCodes.MODIFYSERVICE_TAB_ITEM,
				StaticCodes.MODIFYSERVICE_TAB_ITEM);

		return actionMapping.findForward("partners");
	}

	private void populatePartnersMaps(ServicePartnersListForm servicePartnersLF) {

		// set associated partners first
		List<HTMLOption> associatedDistPartners = new ArrayList<HTMLOption>();
		List<HTMLOption> associatedSourcePartners = new ArrayList<HTMLOption>();
		IPartnerManagement partnerManager = PartnerManager.getInstance();
		Set<Partner> allPartnersAssociatedWithService = partnerManager
				.getAllPartnersAssociatedWithService(Long
						.parseLong(servicePartnersLF.getContextId()));
		if (allPartnersAssociatedWithService != null){
			for (Partner partner : allPartnersAssociatedWithService) {
				String partnerId = String.valueOf(partner.getId());
				String name = partner.getName();
				if (partner.getType().equals(PartnerType.SOURCE)) {
					associatedSourcePartners.add(new HTMLOption(name, partnerId));
				} else if (partner.getType() == PartnerType.DISTRIBUTION) {
					associatedDistPartners.add(new HTMLOption(name, partnerId));
				}
			}
		}
		
		logger.debug("associatedDistPartners.size()="
				+ associatedDistPartners.size());
		logger.debug("associatedSourcePartners.size()="
				+ associatedSourcePartners.size());
		
		Collections.sort(associatedDistPartners);
		Collections.sort(associatedSourcePartners);
		
		servicePartnersLF.setAssociatedDistPartners(associatedDistPartners);
		servicePartnersLF.setAssociatedSourcePartners(associatedSourcePartners);

		// get all the partners and determine which are not associated yet
		List<HTMLOption> unassociatedDistPartners = new ArrayList<HTMLOption>();
		List<HTMLOption> unassociatedSourcePartners = new ArrayList<HTMLOption>();

		List<Partner> allPartners = partnerManager.getAllActivePartners();
		for (Partner partner : allPartners) {
			String partnerId = String.valueOf(partner.getId());
			String name = partner.getName();
			HTMLOption htmlOption = new HTMLOption(name, partnerId);
			if (partner.getType().equals(PartnerType.SOURCE)
					&& !associatedSourcePartners.contains(htmlOption)) {
				unassociatedSourcePartners.add(htmlOption);
			} else if (partner.getType() == PartnerType.DISTRIBUTION
					&& !associatedDistPartners.contains(htmlOption)) {
				unassociatedDistPartners.add(htmlOption);
			}
		}
		logger.debug("unassociatedDistPartners.size()="
				+ unassociatedDistPartners.size());
		logger.debug("unassociatedSourcePartners.size()="
				+ unassociatedSourcePartners.size());
		Collections.sort(unassociatedDistPartners);
		Collections.sort(unassociatedSourcePartners);
		servicePartnersLF.setUnassociatedDistPartners(unassociatedDistPartners);
		servicePartnersLF
				.setUnassociatedSourcePartners(unassociatedSourcePartners);

	}

	@SuppressWarnings("unchecked")
	public ActionForward savePartnersForService(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		ServicePartnersListForm servicePartnersLF = (ServicePartnersListForm) actionForm;

		String contextId = servicePartnersLF.getContextId();
		logger.debug("servicePartnersLF.getContextId()=" + contextId);

		ICacheService<IContainer> containerCache = (ICacheService<IContainer>) ServiceRegistry
				.getDefault().lookup(CONTAINER_CACHE_SERVICE_NAME);
		IContainer container = containerCache.get(new Long(contextId));
		long serviceId = -1;
		
		String serviceName = ((Service) container).getName();
		servicePartnersLF.setName(serviceName);
		serviceId = ((Service) container).getId();
		servicePartnersLF.setId(String.valueOf(serviceId));
		Service service = serviceManager.getService(serviceId);
		prepareService(servicePartnersLF, service);
		service = serviceManager.updateService(service);
		servicePartnersLF.setId(String.valueOf(service.getId()));

		request.setAttribute(StaticCodes.OUTPUT_DATA, servicePartnersLF);

		return actionMapping.findForward("serviceSaved");

	}

	private void prepareService(ServicePartnersListForm servicePartnersLF,
			Service service) {
		String[] associatedDistPartners = servicePartnersLF
				.getSelectedAssociatedDistPartners();
		String[] associatedSourcePartners = servicePartnersLF
				.getSelectedAssociatedSourcePartners();
		logger.debug("There are " + associatedDistPartners.length
				+ " assoc. dist partners");
		logger.debug("There are " + associatedSourcePartners.length
				+ " assoc. source partners");

		IPartnerManagement partnerManager = PartnerManager.getInstance();
		Set<Partner> partnerSet = new HashSet<Partner>();
		for (int i = 0; i < associatedDistPartners.length; i++) {
			logger.debug("associatedDistPartners[i]="
					+ associatedDistPartners[i]);
			Partner partner = partnerManager.getPartner(Long
					.parseLong(associatedDistPartners[i]));
			partnerSet.add(partner);
		}
		for (int i = 0; i < associatedSourcePartners.length; i++) {
			logger.debug("associatedSourcePartners[i]="
					+ associatedSourcePartners[i]);
			Partner partner = partnerManager.getPartner(Long
					.parseLong(associatedSourcePartners[i]));
			partnerSet.add(partner);
		}

		service.setPartners(partnerSet);
	}

	@SuppressWarnings("unchecked")
	public ActionForward getJobsForService(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		JobListForm jobListForm = (JobListForm) actionForm;
		String contextId = jobListForm.getContextId();

		logger.debug("Service Context id --->" + contextId);

		List<JobForm> jobForms = new ArrayList<JobForm>();

		IJobManager jobManager = JobManager.getInstance();
		List<Job> lsJobs = jobManager.getAllJobs(Long.parseLong(contextId));

		JobForm jobForm = null;
		for (Job job : lsJobs) {
			jobForm = new JobForm();
			jobForm = prepareJobForm(job, jobForm);
			jobForms.add(jobForm);
		}

		int iTotalRecords;
		if (lsJobs != null)
			iTotalRecords = lsJobs.size();
		else
			iTotalRecords = 0;
		logger.debug("Total number of records -->" + iTotalRecords);
		jobListForm.setTotalRecords(iTotalRecords);

		ICacheService<IContainer> containerCache = (ICacheService<IContainer>) ServiceRegistry
				.getDefault().lookup(CONTAINER_CACHE_SERVICE_NAME);
		IContainer container = containerCache.get(new Long(contextId));
		ContainerType containerType = container.getContainerType();
		if (containerType == ContainerType.SERVICE) {// it must be!!!
			String serviceName = ((Service) container).getName();
			jobListForm.setName(serviceName);
			jobListForm.setEntityType(container.getContainerType().toString());
		} else {
			jobListForm.setEntityType(container.getContainerType().toString());
		}

		jobListForm.setJobList(jobForms);
		request.setAttribute(StaticCodes.SEARCH_CRITERIA, jobListForm);
		request.setAttribute(StaticCodes.MODIFYSERVICE_TAB_ITEM,
				StaticCodes.MODIFYSERVICE_TAB_ITEM);

		return actionMapping.findForward(JOBS);
	}

	private JobForm prepareJobForm(Job job, JobForm jobForm) {

		jobForm.setId(job.getId());
		jobForm.setName(job.getName());
		jobForm.setSelectedTemplate(job.getTemplateName());
		jobForm.setSelectedPriority(job.getPriority().name());
		jobForm.setScheduleRule(job.getScheduleRuleString());
		if ((job.isTitleAssociated())) {
			jobForm.setIsAssociatedWithTitles("YES");
		} else {
			jobForm.setIsAssociatedWithTitles("NO");
		}

		return jobForm;
	}

	@SuppressWarnings("unchecked")
	public ActionForward getCurrentSchedulesForService(
			ActionMapping actionMapping, ActionForm actionForm,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		ScheduleListForm scheduleListForm = (ScheduleListForm) actionForm;
		String contextId = scheduleListForm.getContextId();

		logger.debug("Service Context id --->" + contextId);

		List<ScheduleForm> scheduleForms = new ArrayList<ScheduleForm>();
		Collection<Schedule> lsSchedules = null;
		ICacheService<IContainer> containerCache = (ICacheService<IContainer>) ServiceRegistry
				.getDefault().lookup(CONTAINER_CACHE_SERVICE_NAME);
		IContainer container = containerCache.get(new Long(contextId));

		lsSchedules = GUISearchHelper.getCurrentPitchSchedules(new Long(
				contextId));
		Service service = (Service) container;
		String serviceName = service.getName();
		scheduleListForm.setName(serviceName);
		ScheduleForm scheduleForm = null;
		int iTotalRecords;
		if (lsSchedules != null) {
			for (Schedule schedule : lsSchedules) {
				scheduleForm = new ScheduleForm();
				scheduleForm = prepareScheduleForm(schedule, scheduleForm);
				scheduleForms.add(scheduleForm);
			}
			iTotalRecords = lsSchedules.size();
		} else
			iTotalRecords = 0;
		logger.debug("Total number of records -->" + iTotalRecords);
		scheduleListForm.setTotalRecords(iTotalRecords);

		scheduleListForm.setScheduleList(scheduleForms);
		request.setAttribute(StaticCodes.SEARCH_CRITERIA, scheduleListForm);
		request.setAttribute(StaticCodes.MODIFYSERVICE_TAB_ITEM,
				StaticCodes.MODIFYSERVICE_TAB_ITEM);

		return actionMapping.findForward(SCHEDULES);
	}

	private ScheduleForm prepareScheduleForm(Schedule schedule,
			ScheduleForm scheduleForm) {

		scheduleForm.setScheduleId(Long.toString(schedule.getId()));
		scheduleForm.setStatus(schedule.getStatus().name());
		scheduleForm.setDate(CommonUtils.formatDate(schedule.getDate()));
		return scheduleForm;
	}

}
