package org.datavaultplatform.broker.services;

import org.datavaultplatform.common.model.Vault;
import org.datavaultplatform.common.model.VaultReview;
import org.datavaultplatform.common.model.dao.VaultReviewDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class VaultsReviewService {

    private static final Logger logger = LoggerFactory.getLogger(VaultsReviewService.class);

    private VaultReviewDAO vaultReviewDAO;

    public void setVaultReviewDAO(VaultReviewDAO vaultReviewDAO) {
        this.vaultReviewDAO = vaultReviewDAO;
    }

    public VaultReview createVaultReview(Vault vault) {
        VaultReview vaultReview = new VaultReview();

        vaultReview.setCreationTime(new Date());
        vaultReview.setVault(vault);

        vaultReviewDAO.save(vaultReview);

        return vaultReview;
    }

    public void addVaultReview(VaultReview vaultReview) {
        vaultReviewDAO.save(vaultReview);
    }

    public List<VaultReview> getVaultReviews() {
        return vaultReviewDAO.list();
    }

    public VaultReview getVaultReview(String vaultReviewID) {
        return vaultReviewDAO.findById(vaultReviewID);
    }

    public List<VaultReview> search(String query) {
        return this.vaultReviewDAO.search(query);
    }
    
    public void updateVaultReview(VaultReview vaultReview) {
        vaultReviewDAO.update(vaultReview);
    }

    public List<Vault> getVaultsForReview(List<Vault> vaults) {
        List<Vault> vaultsForReview = new ArrayList<>();

        for (Vault vault : vaults) {
            if (isVaultForReview(vault)) {
                vaultsForReview.add(vault);
            }
        }

        return vaultsForReview;
    }

    /*
     Returns true if the vault is due for review, or is currently being reviewed.
     */
    public boolean isVaultForReview(Vault vault) {

        Date today = new Date();

        Calendar c = Calendar.getInstance();
        c.setTime(vault.getReviewDate());
        c.add(Calendar.MONTH, -3);
        Date reviewDateMinus3 = c.getTime();

        if (today.after(reviewDateMinus3)) {

            // Looks like its due for review, but has the review already happened.

            boolean currentReviewExists = false;

            for (VaultReview vr : vault.getVaultReviews()) {

                if ((vr.getActionedDate() != null) && ((vr.getActionedDate().after(reviewDateMinus3)))) {

                    // A review has already happened since the review date
                    currentReviewExists = true;
                }
            }

            if (!currentReviewExists) {
                return true;
            }
        }

        return false;
    }


    /*
     Returns true only if the vault is due for review.
     */
    public boolean dueForReviewEmail(Vault vault) {

        Date today = new Date();

        Calendar c = Calendar.getInstance();
        c.setTime(vault.getReviewDate());
        c.add(Calendar.MONTH, -3);
        Date reviewDateMinus3 = c.getTime();

        if (today.after(reviewDateMinus3)) {

            // Looks like its due an email, but check if a review is already underway or has happened.

            boolean currentReviewExists = false;
            for (VaultReview vr : vault.getVaultReviews()) {

                if ((vr.getActionedDate() == null)) {
                    // A review is underway
                    currentReviewExists = true;
                } else {
                    if (vr.getActionedDate().after(reviewDateMinus3)) {
                        // A review has already happened since the review date
                        currentReviewExists = true;
                    }
                }
            }

            if (!currentReviewExists) {
                return true;
            }
        }

        return false;
    }

}


@@ -493,24 +493,239 @@
 ce.class);%0A%0A
+    // The number of months before review date at which people should be notified.%0A    // This could be moved into datavault.properties if they keep on changing their minds about the value.%0A    private int x = -6;%0A%0A
     private 
@@ -2303,34 +2303,33 @@
 Calendar.MONTH, 
--3
+x
 );%0A        Date 
@@ -2335,33 +2335,33 @@
  reviewDateMinus
-3
+x
  = c.getTime();%0A
@@ -2392,33 +2392,33 @@
 (reviewDateMinus
-3
+x
 )) %7B%0A%0A          
@@ -2701,17 +2701,17 @@
 ateMinus
-3
+x
 )))) %7B%0A%0A
@@ -3268,10 +3268,9 @@
 TH, 
--3
+x
 );%0A 
@@ -3296,17 +3296,17 @@
 ateMinus
-3
+x
  = c.get
@@ -3349,25 +3349,25 @@
 iewDateMinus
-3
+x
 )) %7B%0A%0A      
@@ -3816,9 +3816,9 @@
 inus
-3
+x
 )) %7B

Change to review vaults at 6 months rather than 3