package mil.dds.anet.threads;

import java.lang.invoke.MethodHandles;
import java.time.Instant;
import java.util.Collections;
import java.util.List;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import mil.dds.anet.beans.ApprovalAction;
import mil.dds.anet.beans.Report;
import mil.dds.anet.beans.Report.ReportState;
import mil.dds.anet.beans.search.ReportSearchQuery;
import mil.dds.anet.config.AnetConfiguration;
import mil.dds.anet.database.ReportDao;
import mil.dds.anet.utils.AnetAuditLogger;
import mil.dds.anet.utils.DaoUtils;

public class ReportPublicationWorker implements Runnable {

	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
	private final Integer nbOfHoursQuarantineApproved;
	private ReportDao dao;

	public ReportPublicationWorker(ReportDao dao, AnetConfiguration config) {
		this.dao = dao;
		this.nbOfHoursQuarantineApproved = (Integer) config.getDictionaryEntry("reportWorkflow.nbOfHoursQuarantineApproved");
	}

	@Override
	public void run() {
		logger.debug("Report Publication Worker waking up to check for reports to be published");
		try {
			runInternal();
		} catch (Throwable e) { 
			//Cannot let this thread die. Otherwise ANET will stop checking for reports which are to be published. 
			logger.error("Exception in run()", e);
		}
	}

	private void runInternal() {
		//Get a list of all APPROVED reports
		ReportSearchQuery query = new ReportSearchQuery();
		query.setPageSize(Integer.MAX_VALUE);
		query.setState(Collections.singletonList(ReportState.APPROVED));
		List<Report> reports = dao.search(query).getList();
		for (Report r : reports) {
			final List<ApprovalAction> approvalStatus = r.getApprovalStatus();
			if (approvalStatus.get(approvalStatus.size()-1).getCreatedAt().isBefore(Instant.now().atZone(DaoUtils.getDefaultZoneId()).minusHours(this.nbOfHoursQuarantineApproved).toInstant())) {
				//Publish the report
				try { 
					final int numRows = dao.publish(r, null);
					if (numRows == 0) {
						throw new WebApplicationException("Couldn't process report publication", Status.NOT_FOUND);
					}

					AnetAuditLogger.log("report {} automatically published by the ReportPublicationWorker", r.getUuid());

				} catch (Exception e) { 
					logger.error("Exception when publishing report", e);
				}
			}
		}
	}

}

@@ -141,16 +141,38 @@
 il.List;
+%0Aimport java.util.Map;
 %0A%0Aimport
@@ -309,16 +309,54 @@
 ctory;%0A%0A
+import mil.dds.anet.AnetObjectEngine;%0A
 import m
@@ -847,16 +847,47 @@
 lass());
+%0A%0A%09private final ReportDao dao;
 %0A%09privat
@@ -940,29 +940,49 @@
 private 
-ReportDao dao
+final Map%3CString, Object%3E context
 ;%0A%0A%09publ
@@ -1189,16 +1189,78 @@
 oved%22);%0A
+%09%09this.context = AnetObjectEngine.getInstance().getContext();%0A
 %09%7D%0A%0A%09@Ov
@@ -1660,16 +1660,22 @@
 ports%0A%09%09
+final 
 ReportSe
@@ -1826,16 +1826,22 @@
 ED));%0A%09%09
+final 
 List%3CRep
@@ -1871,16 +1871,28 @@
 ch(query
+, null, true
 ).getLis
@@ -1903,16 +1903,22 @@
 %0A%09%09for (
+final 
 Report r
@@ -1980,19 +1980,20 @@
 tus = r.
-get
+load
 Approval
@@ -1999,16 +1999,30 @@
 lStatus(
+context).join(
 );%0A%09%09%09if

Fix the report publication worker