package routines;

import java.util.Date;

import java.text.SimpleDateFormat;
import java.text.ParseException;

public class ValidityCheck {
	private static LcagLogger log = LcagLogger.getLogger(ValidityCheck.class);

	public enum CheckResult
	{
		 TO_FROM_SWITCHED
		,EXTENDS_BEFORE
		,EXTENDS_AFTER 	
		,OVERLAPS_WITH_START 
		,OVERLAPS_WITH_END 	
		,CONTAINS 			
		,HAS_GAP_BEFORE 		
		,HAS_GAP_AFTER
		,FIRSTINSERT
		,EQUALS
		,SHORTENED
		,SETVALIDFROM
		,UNKNOWN
	}
	
	public enum ResultInsertUpdate
	{
		 INSERT
		,UPDATE
		,ERROR 	
	}
	
	public enum ResultValidityCheck
	{
		 OK
		,ERROR
	}
	
	
    /**
     * validityCheckResult: Checks the timeline of the validities  
     * 
     * {talendTypes} Date
     * 
     * {Category} ValidityCheck
     * 
     * {param} Dated(Date existing_validFrom, Date existing_validTo, Date new_validFrom,Date new_validTo) input: Dates to check.
     * 
     * {example} helloExemple(2018-03-02,2099-12-31,2013-01-01,2018-03-01) # EXTENDS_AFTER !.
     */
	public static CheckResult timelineValidity(Date existing_validFrom, Date existing_validTo, Date new_validFrom,Date new_validTo){
		
		
		CheckResult checkResult=CheckResult.UNKNOWN;
		
		if (existing_validFrom == null && existing_validTo==null) 
		{
			//First insert of a record -> no date exists
			log.debug("CheckResult.FIRSTINSERT");
			return CheckResult.FIRSTINSERT;
		}
		
		
		
		if (new_validFrom == null && new_validTo==null) 
		{
			log.debug("existing_validFrom:" + existing_validFrom.toString());
			log.debug("existing_validTo:"   + existing_validTo.toString());
			//No Gap (Related Check)
			log.debug("CheckResult.HAS_GAP_AFTER1");
			return CheckResult.HAS_GAP_AFTER;
		}
		
		//log.debug("diffDate(existing_validTo,constant.getFarPastDate()):"   + String.valueOf(diffDate(existing_validTo,constant.getFarPastDate())));
		//log.debug("diffDate(existing_validFrom,new_validFrom):"   + String.valueOf(diffDate(existing_validTo,constant.getFarPastDate())));
		log.debug("diffDate(existing_validTo,new_validTo):"   + String.valueOf(diffDate(existing_validTo,new_validTo)));
		
		
		if (diffDate(existing_validTo,constant.getFarFutureDate()) ==0 && diffDate(existing_validFrom,new_validFrom)==0 && diffDate(existing_validTo,new_validTo)<0) 
		{
			// MDM  *......* (2010 to 2099)
			// Inc  *...*    (2010 to 2050)
			
			log.debug("CheckResult.SHORTENED");
			return CheckResult.SHORTENED;
		}
		
		if (diffDate(existing_validFrom,constant.getFarPastDate()) ==0 && diffDate(existing_validTo,new_validTo)==0 && diffDate(existing_validFrom,new_validFrom)>0) 
		{
			// MDM  *......* (1970 to 2099)
			// Inc  *...*    (2015 to 2099)
			
			log.debug("CheckResult.SETVALIDFROM");
			return CheckResult.SETVALIDFROM;
		}
		
		log.debug("existing_validFrom:" + existing_validFrom.toString());
		log.debug("existing_validTo:"   + existing_validTo.toString());
		log.debug("new_validFrom:"   + (new_validFrom.equals(null)?"NULL":new_validFrom.toString()));
		log.debug("new_validTo:"   + new_validTo.toString());
		
		log.debug("diffDate(new_validFrom,new_validTo):"   + String.valueOf(diffDate(new_validFrom,new_validTo)));
		log.debug("diffDate(existing_validFrom,new_validFrom):"   + String.valueOf(diffDate(existing_validFrom,new_validFrom)));
		log.debug("diffDate(existing_validTo,new_validTo):"   + String.valueOf(diffDate(existing_validTo,new_validTo)));
		
		if (diffDate(new_validFrom,existing_validFrom)==0 && diffDate(new_validTo,existing_validTo)==0) 
		{
			//First insert of a record -> no date exists
			log.debug("CheckResult.EQUALS");
			return CheckResult.EQUALS;
		}
		
		if (diffDate(new_validFrom,new_validTo)<=0){
			checkResult=CheckResult.TO_FROM_SWITCHED;
			log.debug("CheckResult.TO_FROM_SWITCHED");
		}else{
			/*
			 * existing *-----*
			 * new             *----*
			 */
			if (diffDate(existing_validTo,new_validFrom)==1){
				checkResult=CheckResult.EXTENDS_AFTER;
				log.debug("CheckResult.EXTENDS_AFTER");
			}
			/*
			 * existing *------*
			 * new           *----*
			 */
			if (diffDate(existing_validTo, new_validFrom)<0 &&
				diffDate(existing_validTo, new_validTo)>0	){
				checkResult=CheckResult.OVERLAPS_WITH_END;
				log.debug("CheckResult.OVERLAPS_WITH_END");
			}
			/*
			 * existing *------*
			 * new                 *----*
			 */
			if (diffDate(existing_validTo,new_validFrom)>1){
				checkResult=CheckResult.HAS_GAP_AFTER;
				log.debug("CheckResult.HAS_GAP_AFTER");
				log.debug("diffDate(existing_validTo,new_validFrom)" + String.valueOf(diffDate(existing_validTo,new_validFrom)));
			}
			/*
			 * existing       *------*
			 * new      *----*
			 */
			if (diffDate(new_validTo, existing_validFrom)==1){
				checkResult=CheckResult.EXTENDS_BEFORE;
				log.debug("CheckResult.EXTENDS_BEFORE");
			}
			/*
			 * existing           *------*
			 * new      *----*
			 */
			if (diffDate(existing_validFrom,new_validTo)<-1){
				checkResult=CheckResult.HAS_GAP_BEFORE;
				log.debug("CheckResult.HAS_GAP_BEFORE");
			}
			
						
			/*
			 * existing    *------*
			 * new           -----*
			log.debug("## contains");
			log.debug("## diffDate("+existing_validFrom+","+new_validFrom+"):"+diffDate(existing_validFrom,new_validFrom));
			log.debug("## diffDate("+existing_validTo+","+new_validTo+"):"+diffDate(existing_validTo,new_validTo));
			 */
			if (diffDate(existing_validFrom,new_validFrom) >0 &&
				diffDate(existing_validTo,new_validTo)<=0 ){
				checkResult=CheckResult.CONTAINS;
				log.debug("CONTAINS ENTERED");
			}
			/*
			 * existing      *------*
			 * new        *----*
			 
			log.debug("## OVERLAPS_WITH_START");
			log.debug("## diffDate("+existing_validFrom+","+ new_validTo+"):"+diffDate(existing_validFrom, new_validTo));
			log.debug("## diffDate("+existing_validFrom+","+ new_validFrom+"):"+diffDate(existing_validFrom, new_validFrom));
			*/
			if (diffDate(existing_validFrom, new_validTo)>0 &&
				diffDate(existing_validFrom, new_validFrom)<0 			){
				checkResult=CheckResult.OVERLAPS_WITH_START;
				log.debug("OVERLAPS_WITH_START");
			}
			
		}
		
		return checkResult;
		
	}
	
	
	private static long diffDate(Date d1, Date d2){
		return TalendDate.diffDate(d2,d1,"dd",true);
	}
	
	public static Date calc_ValidFrom(Date existing_validFrom,  Date new_validFrom){
	
		Date initValidFromDate = null;
		Date dresult = null;
		Date curDate = null;
		
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		Date date = new Date();
		String strcurDate = dateFormat.format(date);
		
		if (new_validFrom == null) new_validFrom = constant.getFarPastDate();
		
		try {
			curDate = dateFormat.parse(strcurDate);
			log.debug("curDate:"+curDate.toString());
		}
		catch (ParseException e)
		{}
		
		log.debug("calc_ValidFrom(existing_validFrom = %s, new_validFrom = %s) called", existing_validFrom, new_validFrom);
		
		try 
		{		
			SimpleDateFormat textFormat = new SimpleDateFormat("yyyy-MM-dd");
			String paramDateAsString = "1970-01-01";
			initValidFromDate = textFormat.parse(paramDateAsString);
		
			if ( TalendDate.diffDate(existing_validFrom,initValidFromDate,"dd") == 0)
			{
				log.debug("calc_ValidFrom: ValidFrom in MDM is DefaultDate");
				//MDM enthält default Wert
				if ( TalendDate.diffDate(new_validFrom,initValidFromDate,"dd") == 0)
				{
					log.debug("calc_ValidFrom: ValidFrom in msg is DefaultDate => use Default date");
					//auch Message enthält default Wert
					dresult = initValidFromDate; 
				}
				else
				{
					log.debug("calc_ValidFrom: ValidFrom in msg is NOT DefaultDate => use msg date");
					dresult = new_validFrom;
				}
				
			}
			else
			{
				log.debug("calc_ValidFrom: ValidFrom in MDM is NOT DefaultDate");
				
				//MDM enthält KEINE default Wert
				if ( TalendDate.diffDate(new_validFrom,initValidFromDate,"dd") == 0)
				{
					log.debug("calc_ValidFrom: ValidFrom in msg is DefaultDate => use MDM date");
					// Message enthält default Wert
					dresult = existing_validFrom; 
					
					
				}
				else
				{	
					if ( TalendDate.diffDate(new_validFrom,curDate,"dd") < 0)
					{
						//log.debug("calc_ValidFrom: ValidFrom in msg is in PAST => use MDM date");
						dresult = existing_validFrom;
						
						// 2021-02-21: deactivate condition to allow Update in past
						log.debug("calc_ValidFrom: ValidFrom in msg is in PAST => use Msg date (changed 2021-02-21)");
						dresult = new_validFrom; 
					}
					else
					{
						log.debug("calc_ValidFrom: ValidFrom in msg is NOT in PAST => use Msg date");
						dresult = new_validFrom; 
					}
				
				}
				
				
			}
			
			
		}
		catch (ParseException e) {
		
			
		}
		
		log.debug("calc_ValidFrom: Returning %s", dresult);
		return dresult;
		
	}
	
	public static Date calc_ValidTo(Date existing_validTo,  Date new_validTo){
		
		Date initValidToDate = null;
		Date dresult = null;
	
		if (new_validTo == null) new_validTo = constant.getFarFutureDate();
		
		log.debug("calc_ValidTo(existing_validTo = %s, new_validTo = %s) called", existing_validTo, new_validTo);

		try 
		{		
			SimpleDateFormat textFormat = new SimpleDateFormat("yyyy-MM-dd");
			String paramDateAsString = "2099-12-31";
			initValidToDate = textFormat.parse(paramDateAsString);
		
			if ( TalendDate.diffDate(existing_validTo,initValidToDate,"dd") == 0)
			{
				log.debug("calc_ValidTo: ValidTo in MDM is DefaultDate");
				//MDM enthält default Wert
				if ( TalendDate.diffDate(new_validTo,initValidToDate,"dd") == 0)
				{
					log.debug("calc_ValidTo: ValidTo in Msg is also DefaultDate => use Default Date");
					//auch Message enthält default Wert
					dresult = initValidToDate; 
				}
				else
				{
					log.debug("calc_ValidTo: but ValidTo in Msg is NOT DefaultDate => use Msg Date");
					dresult = new_validTo;
				}
				
			}
			else
			{
				log.debug("calc_ValidTo: ValidTo in MDM is NOT DefaultDate");
				
				//MDM enthält KEINE default Wert
				if ( TalendDate.diffDate(new_validTo,initValidToDate,"dd") == 0)
				{
					log.debug("calc_ValidTo: and ValidTo in Msg is DefaultDate => use MDM Date");
					// Message enthält default Wert
					dresult = existing_validTo; 
				}
				else
				{
					log.debug("calc_ValidTo: and ValidTo in Msg is also NOT DefaultDate => use Msg Date");
					dresult = new_validTo;
				}
				
				
			}
			
			
		}
		catch (ParseException e) {
		
			
		}
		
		log.debug("calc_ValidTo: Returning %s", dresult);
		return dresult;
		
	}
	
    public static ResultInsertUpdate DetermineIfInsOrUpd(Date existing_validFrom, Date existing_validTo, Date new_validFrom,Date new_validTo, String ValidityResult, String isNew)
    {
		
		//ONLY IF MDM is not set to default and Values from Incoming Message is NOT set to defaults
    //	log.debug("Enter DetermineIfInsOrUpd");
    //	log.debug("existing_validFrom:" + existing_validFrom.toString());
	//	log.debug("existing_validTo:"   + existing_validTo.toString());
	//	log.debug("new_validFrom:"   + (new_validFrom.equals(null)?"NULL":new_validFrom.toString()));
	//	log.debug("new_validTo:"   + new_validTo.toString());
		log.debug("DetermineIfInsOrUpd: checking ValidityResult:"   + ValidityResult);
    	
    	ResultInsertUpdate rInsUpd= ResultInsertUpdate.ERROR;
		
		if (ValidityResult.contains("EXTENDS_AFTER") ||  ValidityResult.contains("EXTENDS_BEFORE") ||  ValidityResult.contains("HAS_GAP_AFTER") ||  ValidityResult.contains("HAS_GAP_BEFORE") ||  ValidityResult.contains("TO_FROM_SWITCHED") || (ValidityResult.contains("SETVALIDFROM") && "new".equals(isNew)) ) 
		{
			//First insert of a record -> no date exists
			log.debug("ResultInsertUpdate.INSERT");
			return ResultInsertUpdate.INSERT;
		}
		
		if (ValidityResult.contains("EQUALS") ||  ValidityResult.contains("SHORTENED")) 
		{
			//First insert of a record -> no date exists
			log.debug("ResultInsertUpdate.EQUALS");
			return ResultInsertUpdate.UPDATE;
		}
		
		if (ValidityResult.contains("OVERLAPS_WITH_START") ||  ValidityResult.contains("OVERLAPS_WITH_END") ||  ValidityResult.contains("CONTAINS")) 
		{
			//First insert of a record -> no date exists
			log.debug("ResultInsertUpdate.ERROR");
			return ResultInsertUpdate.ERROR;
		}
		
		return rInsUpd;
				
	}
    
    public static String DetermineIfValidityCheckOK(Date existing_validFrom, Date existing_validTo, Date new_validFrom,Date new_validTo, String ValidityResult, String OPType)
    {
		
		//ONLY IF MDM is not set to default and Values from Incoming Message is NOT set to defaults
    //	log.debug("Enter DetermineIfValidityCheckOK");
    //	log.debug("existing_validFrom:" + existing_validFrom.toString());
	//	log.debug("existing_validTo:"   + existing_validTo.toString());
	//	log.debug("new_validFrom:"   + (new_validFrom.equals(null)?"NULL":new_validFrom.toString()));
	//	log.debug("new_validTo:"   + new_validTo.toString());
	//	log.debug("ValidityResult:"   + ValidityResult);
		
		String rValChck= "OPType";
		
		if ("INSERT".equals(OPType))
		{
			if (existing_validFrom  == null && existing_validTo== null) 
			{
				if ("FIRSTINSERT".equals(ValidityResult))
				{
					log.debug("CheckResult.FIRSTINSERT");
					return "OK";
				}
				else
				{
					log.debug("!FIRSTINSERT");
					return "ERROR";
				}
			}
			else
			{
				if (ValidityResult.contains("EXTENDS_AFTER") ||  ValidityResult.contains("EXTENDS_BEFORE") ||  ValidityResult.contains("HAS_GAP_AFTER") ||  ValidityResult.contains("HAS_GAP_BEFORE") ||  ValidityResult.contains("TO_FROM_SWITCHED")) 
				{ //for inserts
					log.debug("EXTENDS_AFTER....");
					return "OK";
				}
				else
				{ //for inserts
					log.debug("!EXTENDS_AFTER....");
					return "ERROR";
				}
			}
		}
		
		
		if ("UPDATE".equals(OPType))
		{
			if 
			(
					(TalendDate.diffDate(existing_validFrom,constant.getFarPastDate(),"dd") == 0)  && 
					(TalendDate.diffDate(existing_validTo,constant.getFarFutureDate(),"dd") == 0)
			)
			{
			    //log.debug("MDM Default Validities");
			    
			    if ((diffDate(existing_validFrom,constant.getFarPastDate()) ==0 && diffDate(existing_validTo,new_validTo)==0 && diffDate(existing_validFrom,new_validFrom)>0) ||  ValidityResult.contains("SETVALIDFROM")) 
				{
					// MDM  *......* (1970 to 2099)
					// Inc  *...*    (2015 to 2099)
					
					log.debug("CheckResult.SETVALIDFROM");
					return "OK";
				}
			    
			    if (ValidityResult.contains("CONTAINS") ||  ValidityResult.contains("EQUALS") ||  ValidityResult.contains("SHORTENED"))
			    {
			    	 log.debug("CONTAINS, EQUALS, SHORTENED");
			    	 return "OK";
			    }
			    else
			    {
			    	 log.debug("!UPDATE....");
			    	return "ERROR";			    	
			    }
			}
			else
			{
				if (ValidityResult.contains("EQUALS") ||  ValidityResult.contains("SHORTENED"))
				{
					 log.debug("SHORTENED....");
			    	 return "OK";
					
				}
			}
			
		}
			
		
		
		
		
	
		
		//MDM has default Validities
		if 
		(
				(TalendDate.diffDate(existing_validFrom,constant.getFarPastDate(),"dd") == 0)  && 
				(TalendDate.diffDate(existing_validTo,constant.getFarFutureDate(),"dd") == 0)
		) 
		{
			    log.debug("MDM Default Validities");
			    
			    if (ValidityResult.contains("UPDATE") ||  ValidityResult.contains("EQUALS"))
			    {
			    	return "OK";
			    }
			    else
			    {
			    	return "ERROR";			    	
			    }
		}
		else
		{
			//MDM element has no default validities
			if (ValidityResult.contains("EXTENDS_AFTER") ||  ValidityResult.contains("EXTENDS_BEFORE") ||  ValidityResult.contains("HAS_GAP_AFTER") ||  ValidityResult.contains("HAS_GAP_BEFORE")) 
			{ //for inserts
				return "OK";
			}
			
			if (ValidityResult.contains("EQUALS") ||  ValidityResult.contains("SHORTENED") ||  ValidityResult.contains("TO_FROM_SWITCHED")) 
			{ //for updates
				return "OK";
			}
			
			if (ValidityResult.contains("OVERLAPS_WITH_START") ||  ValidityResult.contains("OVERLAPS_WITH_END") ) 
			{ //for updates
				return "ERROR";
			}
			
		}
		
		
		
		return rValChck;
				
	}
    
    public static String DetermineIfValidityCheckOK_ALT(Date existing_validFrom, Date existing_validTo, Date new_validFrom,Date new_validTo, String ValidityResult)
    {
		
		//ONLY IF MDM is not set to default and Values from Incoming Message is NOT set to defaults
    	log.debug("Enter DetermineIfValidityCheckOK");
    	log.debug("existing_validFrom:" + existing_validFrom.toString());
		log.debug("existing_validTo:"   + existing_validTo.toString());
		log.debug("new_validFrom:"   + (new_validFrom.equals(null)?"NULL":new_validFrom.toString()));
		log.debug("new_validTo:"   + new_validTo.toString());
		log.debug("ValidityResult:"   + ValidityResult);
    	
		String rValChck= "ERROR";
		
		if (existing_validFrom == null && existing_validTo== null) 
		{
			//log.debug("CheckResult.FIRSTINSERT");
			return "OK";
		}
	
		
		//MDM has default Validities
		if 
		(
				(TalendDate.diffDate(existing_validFrom,constant.getFarPastDate(),"dd") == 0)  && 
				(TalendDate.diffDate(existing_validTo,constant.getFarFutureDate(),"dd") == 0)
		) 
		{
			    log.debug("MDM Default Validities");
			    
			    if (ValidityResult.contains("UPDATE") ||  ValidityResult.contains("EQUALS"))
			    {
			    	return "OK";
			    }
			    else
			    {
			    	return "ERROR";			    	
			    }
		}
		else
		{
			//MDM element has no default validities
			if (ValidityResult.contains("EXTENDS_AFTER") ||  ValidityResult.contains("EXTENDS_BEFORE") ||  ValidityResult.contains("HAS_GAP_AFTER") ||  ValidityResult.contains("HAS_GAP_BEFORE")) 
			{ //for inserts
				return "OK";
			}
			
			if (ValidityResult.contains("EQUALS") ||  ValidityResult.contains("SHORTENED") ||  ValidityResult.contains("TO_FROM_SWITCHED")) 
			{ //for updates
				return "OK";
			}
			
			if (ValidityResult.contains("OVERLAPS_WITH_START") ||  ValidityResult.contains("OVERLAPS_WITH_END") ) 
			{ //for updates
				return "ERROR";
			}
			
		}
		
		
		
		return rValChck;
				
	}
	}
	





