/**
 *
 */
package net.sf.taverna.t2.workbench.report.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import net.sf.taverna.t2.lang.observer.MultiCaster;
import net.sf.taverna.t2.lang.observer.Observable;
import net.sf.taverna.t2.lang.observer.Observer;
import net.sf.taverna.t2.visit.HierarchyTraverser;
import net.sf.taverna.t2.visit.VisitKind;
import net.sf.taverna.t2.visit.VisitReport;
import net.sf.taverna.t2.visit.VisitReport.Status;
import net.sf.taverna.t2.visit.Visitor;
import net.sf.taverna.t2.workbench.edits.EditManager;
import net.sf.taverna.t2.workbench.edits.EditManager.AbstractDataflowEditEvent;
import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent;
import net.sf.taverna.t2.workbench.file.FileManager;
import net.sf.taverna.t2.workbench.file.events.ClosedDataflowEvent;
import net.sf.taverna.t2.workbench.file.events.FileManagerEvent;
import net.sf.taverna.t2.workbench.file.events.SetCurrentDataflowEvent;
import net.sf.taverna.t2.workbench.report.DataflowReportEvent;
import net.sf.taverna.t2.workbench.report.FailedEntityKind;
import net.sf.taverna.t2.workbench.report.IncompleteDataflowKind;
import net.sf.taverna.t2.workbench.report.InvalidDataflowKind;
import net.sf.taverna.t2.workbench.report.ReportManager;
import net.sf.taverna.t2.workbench.report.ReportManagerEvent;
import net.sf.taverna.t2.workbench.report.UnresolvedOutputKind;
import net.sf.taverna.t2.workbench.report.UnsatisfiedEntityKind;
import net.sf.taverna.t2.workbench.report.config.ReportManagerConfiguration;
import net.sf.taverna.t2.workflowmodel.Dataflow;
import net.sf.taverna.t2.workflowmodel.DataflowValidationReport;
import net.sf.taverna.t2.workflowmodel.Processor;

import org.apache.log4j.Logger;

/**
 * @author Alan R Williams
 *
 */
public class ReportManagerImpl implements Observable<ReportManagerEvent>, ReportManager {

	private static final long MAX_AGE_OUTDATED_MILLIS = 1 * 60 * 60 * 1000; // 1 hour
	private static Logger logger = Logger.getLogger(ReportManagerImpl.class);

	private ReportManagerConfiguration reportManagerConfiguration;
	private HierarchyTraverser traverser = null;
	private Map<Dataflow, Map<Object, Set<VisitReport>>> reportMap = Collections
			.synchronizedMap(new WeakHashMap<Dataflow, Map<Object, Set<VisitReport>>>());;
	private Map<Dataflow, Map<Object, Status>> statusMap = Collections
			.synchronizedMap(new WeakHashMap<Dataflow, Map<Object, Status>>());
	private Map<Dataflow, Map<Object, String>> summaryMap = Collections
			.synchronizedMap(new WeakHashMap<Dataflow, Map<Object, String>>());
	private Map<Dataflow, Long> lastCheckedMap = Collections
			.synchronizedMap(new WeakHashMap<Dataflow, Long>());
	private Map<Dataflow, Long> lastFullCheckedMap = Collections
			.synchronizedMap(new WeakHashMap<Dataflow, Long>());
	private Map<Dataflow, String> lastFullCheckedDataflowIdMap = Collections
			.synchronizedMap(new WeakHashMap<Dataflow, String>());

	private EditManager editManager;
	private FileManager fileManager;

	// private Set<Visitor<?>> visitors;

	protected ReportManagerImpl(EditManager editManager, FileManager fileManager,
			Set<Visitor<?>> visitors, ReportManagerConfiguration reportManagerConfiguration)
			throws IllegalStateException {
		this.editManager = editManager;
		this.fileManager = fileManager;
		this.reportManagerConfiguration = reportManagerConfiguration;
		// this.visitors = visitors;
		traverser = new HierarchyTraverser(visitors);
		ReportManagerFileObserver fileObserver = new ReportManagerFileObserver();
		fileManager.addObserver(fileObserver);
		addEditObserver();
		reportManagerConfiguration.applySettings();
	}

	private void addEditObserver() {
		synchronized (editManager) {
			List<Observer<EditManagerEvent>> currentObservers = editManager.getObservers();
			for (Observer<EditManagerEvent> o : currentObservers) {
				editManager.removeObserver(o);
			}
			editManager.addObserver(new ReportManagerEditObserver());
			for (Observer<EditManagerEvent> o : currentObservers) {
				editManager.addObserver(o);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#updateReport(net.sf.taverna.t2.workflowmodel
	 * .Dataflow, boolean, boolean)
	 */
	@Override
	public void updateReport(Dataflow d, boolean includeTimeConsuming, boolean remember) {
		Set<VisitReport> oldTimeConsumingReports = null;
		long time = System.currentTimeMillis();
		long expiration = Integer.parseInt(reportManagerConfiguration
				.getProperty(ReportManagerConfiguration.REPORT_EXPIRATION)) * 60 * 1000;
		if (remember && !includeTimeConsuming
				&& ((expiration == 0) || ((time - getLastFullCheckedTime(d)) < expiration))) {
			oldTimeConsumingReports = getTimeConsumingReports(d);
		}
		Map<Object, Set<VisitReport>> reportsEntry = new HashMap<Object, Set<VisitReport>>();
		Map<Object, Status> statusEntry = new HashMap<Object, Status>();
		Map<Object, String> summaryEntry = new HashMap<Object, String>();
		reportMap.put(d, reportsEntry);
		statusMap.put(d, statusEntry);
		summaryMap.put(d, summaryEntry);
		validateDataflow(d, reportsEntry, statusEntry, summaryEntry);

		Set<VisitReport> newReports = new HashSet<VisitReport>();
		traverser.traverse(d, new ArrayList<Object>(), newReports, includeTimeConsuming);
		for (VisitReport vr : newReports) {
			addReport(reportsEntry, statusEntry, summaryEntry, vr);
		}
		if (oldTimeConsumingReports != null) {
			for (VisitReport vr : oldTimeConsumingReports) {
				addReport(reportsEntry, statusEntry, summaryEntry, vr);
			}
		}
		time = System.currentTimeMillis();
		lastCheckedMap.put(d, time);
		if (includeTimeConsuming) {
			lastFullCheckedMap.put(d, time);
			lastFullCheckedDataflowIdMap.put(d, d.getIdentifier());
		}
		multiCaster.notify(new DataflowReportEvent(d));
	}

	private void updateObjectReportInternal(Dataflow d, Object o) {
		Map<Object, Set<VisitReport>> reportsEntry = reportMap.get(d);
		Map<Object, Status> statusEntry = statusMap.get(d);
		Map<Object, String> summaryEntry = summaryMap.get(d);
		if (reportsEntry == null) {
			logger.error("Attempt to update reports on an object in a dataflow that has not been checked");
			reportsEntry = new HashMap<Object, Set<VisitReport>>();
			statusEntry = new HashMap<Object, Status>();
			summaryEntry = new HashMap<Object, String>();
			reportMap.put(d, reportsEntry);
			statusMap.put(d, statusEntry);
			summaryMap.put(d, summaryEntry);
		} else {
			reportsEntry.remove(o);
			statusEntry.remove(o);
			summaryEntry.remove(o);
		}
		// Assume o is directly inside d
		List<Object> ancestry = new ArrayList<Object>();
		ancestry.add(d);
		Set<VisitReport> newReports = new HashSet<VisitReport>();
		traverser.traverse(o, ancestry, newReports, true);
		for (VisitReport vr : newReports) {
			addReport(reportsEntry, statusEntry, summaryEntry, vr);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#updateObjectSetReport(net.sf.taverna.t2
	 * .workflowmodel.Dataflow, java.util.Set)
	 */
	@Override
	public void updateObjectSetReport(Dataflow d, Set<Object> objects) {
		for (Object o : objects) {
			updateObjectReportInternal(d, o);
		}
		multiCaster.notify(new DataflowReportEvent(d));
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see net.sf.taverna.t2.workbench.report.ReportManagerI#updateObjectReport(net.sf.taverna.t2.
	 * workflowmodel.Dataflow, java.lang.Object)
	 */
	@Override
	public void updateObjectReport(Dataflow d, Object o) {
		updateObjectReportInternal(d, o);
		multiCaster.notify(new DataflowReportEvent(d));
	}

	private Set<VisitReport> getTimeConsumingReports(Dataflow d) {
		Set<VisitReport> result = new HashSet<VisitReport>();
		Map<Object, Set<VisitReport>> currentReports = getReports(d);
		if (currentReports != null) {
			for (Object o : currentReports.keySet()) {
				for (VisitReport vr : currentReports.get(o)) {
					if (vr.wasTimeConsuming()) {
						result.add(vr);
					}
				}
			}
		}
		return result;
	}

	private void removeReport(Dataflow d) {
		reportMap.remove(d);
		statusMap.remove(d);
		summaryMap.remove(d);
	}

	private void addReport(Map<Object, Set<VisitReport>> reports, Map<Object, Status> statusEntry,
			Map<Object, String> summaryEntry, VisitReport newReport) {
		if (newReport.getCheckTime() == 0) {
			newReport.setCheckTime(System.currentTimeMillis());
		}
		Object subject = newReport.getSubject();
		Set<VisitReport> currentReports = reports.get(subject);
		Status newReportStatus = newReport.getStatus();
		if (currentReports == null) {
			currentReports = new HashSet<VisitReport>();
			reports.put(subject, currentReports);
			statusEntry.put(subject, newReportStatus);
			summaryEntry.put(subject, newReport.getMessage());
		} else {
			Status currentStatus = statusEntry.get(subject);
			if (currentStatus.compareTo(newReportStatus) < 0) {
				statusEntry.put(subject, newReportStatus);
				summaryEntry.put(subject, newReport.getMessage());
			} else if (currentStatus.compareTo(newReportStatus) == 0) {
				if (currentStatus.equals(Status.WARNING)) {
					summaryEntry.put(subject, "Multiple warnings");
				} else if (currentStatus.equals(Status.SEVERE)) {
					summaryEntry.put(subject, "Multiple errors");
				}
			}
		}
		currentReports.add(newReport);
	}

	private void validateDataflow(Dataflow d, Map<Object, Set<VisitReport>> reportsEntry,
			Map<Object, Status> statusEntry, Map<Object, String> summaryEntry) {
		DataflowValidationReport validationReport = d.checkValidity();
		if (validationReport.isWorkflowIncomplete()) {
			addReport(reportsEntry, statusEntry, summaryEntry, new VisitReport(
					IncompleteDataflowKind.getInstance(), d, "Incomplete workflow",
					IncompleteDataflowKind.INCOMPLETE_DATAFLOW, VisitReport.Status.SEVERE));
		} else if (!validationReport.isValid()) {
			addReport(reportsEntry, statusEntry, summaryEntry,
					new VisitReport(InvalidDataflowKind.getInstance(), d, "Invalid workflow",
							InvalidDataflowKind.INVALID_DATAFLOW, VisitReport.Status.SEVERE));
		}
		fillInReport(reportsEntry, statusEntry, summaryEntry, validationReport);
	}

	private void fillInReport(Map<Object, Set<VisitReport>> reportsEntry,
			Map<Object, Status> statusEntry, Map<Object, String> summaryEntry,
			DataflowValidationReport report) {
		for (Object o : report.getUnresolvedOutputs()) {
			addReport(reportsEntry, statusEntry, summaryEntry,
					new VisitReport(UnresolvedOutputKind.getInstance(), o,
							"Invalid workflow output", UnresolvedOutputKind.OUTPUT,
							VisitReport.Status.SEVERE));
		}
		for (Object o : report.getFailedEntities()) {
			addReport(reportsEntry, statusEntry, summaryEntry,
					new VisitReport(FailedEntityKind.getInstance(), o,
							"Mismatch of input list depths", FailedEntityKind.FAILED_ENTITY,
							VisitReport.Status.SEVERE));
		}
		for (Object o : report.getUnsatisfiedEntities()) {
			addReport(reportsEntry, statusEntry, summaryEntry, new VisitReport(
					UnsatisfiedEntityKind.getInstance(), o, "Unknown prior list depth",
					UnsatisfiedEntityKind.UNSATISFIED_ENTITY, VisitReport.Status.SEVERE));
		}
		// for (DataflowValidationReport subReport : report.getInvalidDataflows().values()) {
		// fillInReport(descriptionMap, subReport);
		// }
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#getReports(net.sf.taverna.t2.workflowmodel
	 * .Dataflow, java.lang.Object)
	 */
	@Override
	public Set<VisitReport> getReports(Dataflow d, Object object) {
		Set<VisitReport> result = new HashSet<VisitReport>();
		Map<Object, Set<VisitReport>> objectReports = reportMap.get(d);
		if (objectReports != null) {
			Set<Object> objects = new HashSet<Object>();
			objects.add(object);
			if (object instanceof Processor) {
				objects.addAll(((Processor) object).getActivityList());
			}
			for (Object o : objects) {
				if (objectReports.containsKey(o)) {
					result.addAll(objectReports.get(o));
				}
			}
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#getReports(net.sf.taverna.t2.workflowmodel
	 * .Dataflow)
	 */
	@Override
	public Map<Object, Set<VisitReport>> getReports(Dataflow d) {
		return reportMap.get(d);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see net.sf.taverna.t2.workbench.report.ReportManagerI#isStructurallySound(net.sf.taverna.t2.
	 * workflowmodel.Dataflow)
	 */
	@Override
	public boolean isStructurallySound(Dataflow d) {
		Map<Object, Set<VisitReport>> objectReports = reportMap.get(d);
		if (objectReports == null) {
			return false;
		}
		for (Set<VisitReport> visitReportSet : objectReports.values()) {
			for (VisitReport vr : visitReportSet) {
				if (vr.getStatus().equals(Status.SEVERE)) {
					VisitKind vk = vr.getKind();
					if ((vk instanceof IncompleteDataflowKind)
							|| (vk instanceof InvalidDataflowKind)
							|| (vk instanceof UnresolvedOutputKind)
							|| (vk instanceof FailedEntityKind)
							|| (vk instanceof UnsatisfiedEntityKind)) {
						return false;
					}
				}
			}
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#getStatus(net.sf.taverna.t2.workflowmodel
	 * .Dataflow)
	 */
	@Override
	public Status getStatus(Dataflow d) {
		Map<Object, Set<VisitReport>> objectReports = reportMap.get(d);
		if (objectReports == null) {
			return Status.OK;
		}
		Status currentStatus = Status.OK;
		for (Set<VisitReport> visitReportSet : objectReports.values()) {
			for (VisitReport vr : visitReportSet) {
				Status status = vr.getStatus();
				if (status.compareTo(currentStatus) > 0) {
					currentStatus = status;
				}
				if (currentStatus.equals(Status.SEVERE)) {
					return currentStatus;
				}
			}
		}
		return currentStatus;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#getStatus(net.sf.taverna.t2.workflowmodel
	 * .Dataflow, java.lang.Object)
	 */
	@Override
	public Status getStatus(Dataflow d, Object object) {
		Status result = Status.OK;
		Map<Object, Status> statusEntry = statusMap.get(d);
		if (statusEntry != null) {
			Status value = statusEntry.get(object);
			if (value != null) {
				result = value;
			}
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see net.sf.taverna.t2.workbench.report.ReportManagerI#getSummaryMessage(net.sf.taverna.t2.
	 * workflowmodel.Dataflow, java.lang.Object)
	 */
	@Override
	public String getSummaryMessage(Dataflow d, Object object) {
		String result = null;
		if (!getStatus(d, object).equals(Status.OK)) {
			Map<Object, String> summaryEntry = summaryMap.get(d);
			if (summaryEntry != null) {
				result = summaryEntry.get(object);
			}
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see net.sf.taverna.t2.workbench.report.ReportManagerI#getLastCheckedTime(net.sf.taverna.t2.
	 * workflowmodel.Dataflow)
	 */
	@Override
	public long getLastCheckedTime(Dataflow d) {
		Long l = lastCheckedMap.get(d);
		if (l == null) {
			return 0;
		} else {
			return l.longValue();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#getLastFullCheckedTime(net.sf.taverna.t2
	 * .workflowmodel.Dataflow)
	 */
	@Override
	public long getLastFullCheckedTime(Dataflow d) {
		Long l = lastFullCheckedMap.get(d);
		if (l == null) {
			return 0;
		} else {
			return l.longValue();
		}
	}

	/**
	 * @author alanrw
	 *
	 */
	public class ReportManagerFileObserver implements Observer<FileManagerEvent> {

		public void notify(Observable<FileManagerEvent> sender, FileManagerEvent message)
				throws Exception {
			String onOpen = reportManagerConfiguration.getProperty(
					ReportManagerConfiguration.ON_OPEN);
			if (message instanceof ClosedDataflowEvent) {
				ReportManagerImpl.this.removeReport(((ClosedDataflowEvent) message).getDataflow());
			} else if (message instanceof SetCurrentDataflowEvent) {
				Dataflow dataflow = ((SetCurrentDataflowEvent) message).getDataflow();
				if (!reportMap.containsKey(dataflow)) {
					if (!onOpen.equals(ReportManagerConfiguration.NO_CHECK)) {
						updateReport(dataflow,
								onOpen.equals(ReportManagerConfiguration.FULL_CHECK), true);
					} else {
						ReportManagerImpl.this.multiCaster
								.notify(new DataflowReportEvent(dataflow));
					}
				} else {
					ReportManagerImpl.this.multiCaster.notify(new DataflowReportEvent(dataflow));
				}
			}
		}

	}

	private MultiCaster<ReportManagerEvent> multiCaster = new MultiCaster<ReportManagerEvent>(this);

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#addObserver(net.sf.taverna.t2.lang.observer
	 * .Observer)
	 */
	@Override
	public void addObserver(Observer<ReportManagerEvent> observer) {
		multiCaster.addObserver(observer);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see net.sf.taverna.t2.workbench.report.ReportManagerI#getObservers()
	 */
	@Override
	public List<Observer<ReportManagerEvent>> getObservers() {
		return multiCaster.getObservers();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * net.sf.taverna.t2.workbench.report.ReportManagerI#removeObserver(net.sf.taverna.t2.lang.observer
	 * .Observer)
	 */
	@Override
	public void removeObserver(Observer<ReportManagerEvent> observer) {
		multiCaster.removeObserver(observer);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see net.sf.taverna.t2.workbench.report.ReportManagerI#isReportOutdated(net.sf.taverna.t2.
	 * workflowmodel.Dataflow)
	 */
	@Override
	public boolean isReportOutdated(Dataflow dataflow) {
		String lastCheckedId = lastFullCheckedDataflowIdMap.get(dataflow);
		Long lastCheck = lastFullCheckedMap.get(dataflow);
		if (lastCheckedId == null || lastCheck == null) {
			// Unknown, so outdated
			return true;
		}
		if (!lastCheckedId.equals(dataflow.getIdentifier())) {
			// Workflow changed, so outdaeted
			return true;
		}
		long now = System.currentTimeMillis();
		long age = now - lastCheck;
		// Outdated if it is older than the maximum
		return age > MAX_AGE_OUTDATED_MILLIS;
	}

	public class ReportManagerEditObserver implements Observer<EditManagerEvent> {
		public void notify(Observable<EditManagerEvent> sender, EditManagerEvent message)
				throws Exception {
			String onEdit = reportManagerConfiguration
					.getProperty(ReportManagerConfiguration.ON_EDIT);
			Dataflow dataflow = fileManager.getCurrentDataflow();
			if (message instanceof AbstractDataflowEditEvent) {
				AbstractDataflowEditEvent adee = (AbstractDataflowEditEvent) message;
				if (adee.getDataFlow().equals(dataflow)) {
					if (onEdit.equals(ReportManagerConfiguration.QUICK_CHECK)) {
						updateReport(dataflow, false, true);
					} else if (onEdit.equals(ReportManagerConfiguration.FULL_CHECK)) {
						updateReport(dataflow, true, true);
					}
				}
			}
		}
	}

}
