package at.gv.egiz.pdfas.web.helper;

import java.util.Date;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import at.gv.egiz.pdfas.exceptions.ErrorCode;
import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
import at.knowcenter.wag.egov.egiz.pdf.EGIZDate;
import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;

/**
 * This class deals with invalid signing times. 
 * @author tknall
 */
public final class SigningTimeHelper {
   
   private SigningTimeHelper() {
   }
   
   private static Integer tolerance = null;
   
   /**
    * The log.
    */
   private final static Log LOG = LogFactory.getLog(SigningTimeHelper.class);
   
   private final static String SIGNING_TIME_TOLERANCE_KEY = "signing_time_tolerance";
   private final static String FORMAT_UTC_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
   
   public static void checkSigningTimeAgainstHostTime(SignatorInformation si) throws SignatureException {
      checkSigningTimeAgainstHostTime(si.getSignSignatureObject());
   }
   
   public static synchronized void checkSigningTimeAgainstHostTime(SignSignatureObject sso) throws SignatureException {
      if (tolerance == null) {
         try {
            String toleranceString = SettingsReader.getInstance().getSetting(SIGNING_TIME_TOLERANCE_KEY, "-1");
            tolerance = new Integer(Integer.parseInt(toleranceString));
         } catch (NumberFormatException e) {
            LOG.warn("Invalid configuration key = " + SIGNING_TIME_TOLERANCE_KEY + ". Disabling signing time check.");
            tolerance = new Integer(-1);
         } catch (SettingsException e) {
            LOG.error("Error reading settings. Disabling signing time check.", e);
            tolerance = new Integer(-1);
         }
      }
      if (tolerance.intValue() == -1) {
         return;
      }
      
      // signing time
      Date signingTime = EGIZDate.parseDateFromString(sso.getDate());
      
      // current time
      Date currentTime = new Date();
      
      // lower limit
      Date lowerLimit = new Date(currentTime.getTime() - tolerance.intValue()*1000);
      
      // upper limit
      Date upperLimit = new Date(currentTime.getTime() + tolerance.intValue()*1000);
      
      String signingTimeString = DateFormatUtils.formatUTC(signingTime, FORMAT_UTC_DATE_PATTERN);
      
      if (LOG.isDebugEnabled()) {
         String lower = DateFormatUtils.formatUTC(lowerLimit, FORMAT_UTC_DATE_PATTERN);
         String upper = DateFormatUtils.formatUTC(upperLimit, FORMAT_UTC_DATE_PATTERN);
         LOG.debug("Checking if signing time " + signingTimeString + " is valid according to the given time frame [ " + lower + ", " + upper + " ].");
      }
      
      if (signingTime.before(lowerLimit) || signingTime.after(upperLimit)) {
         throw new SignatureException(ErrorCode.INVALID_SIGNING_TIME, "The signing time " + signingTimeString + " is out of the given tolerance of " + tolerance.intValue() + " seconds.");
      }
      
   }
   
}