package usda.weru.weps.wepsDate;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import static java.util.Calendar.YEAR;
import java.util.GregorianCalendar;

/**
 *
 * @author mhaas
 */
public class WepsDateUtils {
    public static final DateFormat parseDateFormat;
    static {
        parseDateFormat = new SimpleDateFormat("dd/MM/yyyy");
        parseDateFormat.setLenient(true);
    }
    public static final int parseDateBaseYear = 2000;
    public static final java.util.Date parseDateIntervalBaseDate;
    static {
        GregorianCalendar myCal = new GregorianCalendar();
        myCal.set(parseDateBaseYear+1, 0, 1);
        parseDateIntervalBaseDate = new java.sql.Date(myCal.getTimeInMillis());
    }
    public static final java.sql.Date parseDateIntervalBaseDateSql = new java.sql.Date(parseDateIntervalBaseDate.getTime());


    
    public static java.util.Date parseDateWeps (String dateStr) throws ParseException {
        return parseDateWeps(dateStr, parseDateFormat);
    }
    
    public static java.util.Date parseDateWeps (String dateStr, DateFormat format) throws ParseException {
        GregorianCalendar myCal = new GregorianCalendar();
        java.util.Date retDate = format.parse(dateStr);
        myCal.setTime(retDate);
        if (myCal.get(Calendar.YEAR) < parseDateBaseYear) {
            myCal.add(Calendar.YEAR, parseDateBaseYear);
        }
        retDate = myCal.getTime();
        return retDate;
    }
    


    public static java.util.Date getDateWeps (java.util.Date date, GregorianCalendar myCal) {
        myCal.setTime(date);

        if (myCal.get(Calendar.YEAR) < parseDateBaseYear) {
            myCal.add(Calendar.YEAR, parseDateBaseYear);
        }
        
        return new java.util.Date(myCal.getTimeInMillis());
    }
    
    public static java.util.Date getDateWeps (java.util.Date date) {
        return getDateWeps (date, new GregorianCalendar());
    }
    
    public static java.util.Date getDateWeps (int year, int month, int day) {
        GregorianCalendar myCal = new GregorianCalendar();
        myCal.set(year, month, day);
        return getDateWeps (new java.sql.Date(myCal.getTimeInMillis()), myCal);
    }
    
    public static java.util.Date getDateWeps (String dateStr) throws ParseException {
        return getDateWeps(parseDateWeps(dateStr), new GregorianCalendar());
    }
    
    
    public static java.sql.Date getSqlDateWeps (java.util.Date date) {
        return new java.sql.Date(getDateWeps (date, new GregorianCalendar()).getTime());
    }
    
    public static java.sql.Date getSqlDateWeps (int year, int month, int day) {
        return new java.sql.Date(getDateWeps (year, month, day).getTime());
    }
    
    public static java.sql.Date getSqlDateWeps (String dateStr) throws ParseException {
        return new java.sql.Date(getDateWeps(parseDateWeps(dateStr), new GregorianCalendar()).getTime());
    }
    

    
    public static java.sql.Date getSqlDateWepsYearEnd (int year) {
        GregorianCalendar myCal = new GregorianCalendar();
        myCal.set(parseDateBaseYear+year, 11, 31);
        return new java.sql.Date(myCal.getTimeInMillis());
    }
    
//    public static int getIntervalLengthDaysOLD(java.util.Date intervalStart, java.util.Date intervalEnd, int rotLength) {
//        GregorianCalendar myCal = new GregorianCalendar();
//        long diffInMillies;
//        if (intervalEnd.after(intervalStart)) {
//            diffInMillies = intervalEnd.getTime() - intervalStart.getTime();
//        } else {
//            // dates wrap
//            java.util.Date manEndDate = getSqlDateWepsYearEnd(rotLength);
//            java.util.Date manStartDate = parseDateIntervalBaseDate;
//            diffInMillies = intervalEnd.getTime() - manStartDate.getTime();
//            diffInMillies += manEndDate.getTime() - intervalStart.getTime();
//            diffInMillies += 1000*60*60*24;
//        }
//        int ciDays = (int)TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
//        
//        int leapDayCnt = 0;
//        java.util.Date checkStart = intervalStart;
//        myCal.setTime(checkStart);
//        int year = myCal.get(Calendar.YEAR);
//        myCal.set(year, 11, 31);
//        java.util.Date checkEnd =  new java.sql.Date(myCal.getTimeInMillis());
//        java.util.Date leapDay;
//        while (checkEnd.before(intervalEnd)) {
//            if(myCal.isLeapYear(year)) {
//                myCal.set(myCal.get(Calendar.YEAR), 1, 29);                
//                leapDay = new java.sql.Date(myCal.getTimeInMillis());
//                if ((leapDay.after(checkStart) && leapDay.before(checkEnd)) || 
//                        leapDay.equals(checkStart) || leapDay.equals(checkEnd)) {
//                    leapDayCnt++;
//                }
//            }
//            checkStart = checkEnd;
//            myCal.setTime(checkStart);
//            myCal.set(++year, 11, 31);
//            checkEnd =  new java.sql.Date(myCal.getTimeInMillis());
//        }
//        if(myCal.isLeapYear(year)) {
//            checkEnd = intervalEnd;
//            myCal.set(myCal.get(Calendar.YEAR), 1, 29);                
//            leapDay = new java.sql.Date(myCal.getTimeInMillis());
//            if ((leapDay.after(checkStart) && leapDay.before(checkEnd)) || 
//                    leapDay.equals(checkStart) || leapDay.equals(checkEnd)) {
//                leapDayCnt++;
//            }
//        }
//        ciDays -= leapDayCnt;
//        
//        if (ciDays < 1) {
//            ciDays = 365;
//        }
//        
//        return ciDays;
//    }
    
    public static int getIntervalLengthDays(java.util.Date intervalStart, java.util.Date intervalEnd, int rotLength) {
        GregorianCalendar myCal = new GregorianCalendar();
        long diffInMillies;
        int ciDays;
        if (intervalEnd.after(intervalStart)) {
            ciDays = (int)(getDaysSinceEpoch365(intervalEnd) - getDaysSinceEpoch365(intervalStart));
        } else {
            // dates wrap
            java.util.Date manEndDate = getSqlDateWepsYearEnd(rotLength);
            java.util.Date manStartDate = parseDateIntervalBaseDate;
            ciDays = (int)(getDaysSinceEpoch365(intervalEnd) - getDaysSinceEpoch365(manStartDate));
            ciDays += (int)(getDaysSinceEpoch365(manEndDate) - getDaysSinceEpoch365(intervalStart));
            ciDays += 1;
        }
        if (ciDays < 1) {
            ciDays = 365;
        }
        
        return ciDays;
    }
    
    public static boolean isDateBeforeYearOne (java.sql.Date checkDate) {
        return checkDate.before(parseDateIntervalBaseDate);
    }
    public static boolean isDateBeforeYearOne (java.util.Date checkDate) {
        return checkDate.before(parseDateIntervalBaseDate);
    }
    
    
    public static long getDaysSinceEpoch365(java.util.Date date) {
        GregorianCalendar myCal = new GregorianCalendar();
        myCal.setTime(date);
        int year = myCal.get(Calendar.YEAR);

        double days = Math.floor(year * 365) + getDaysInYear365(date);
        return (long) days;
    }

    public static int getDaysInYear365(java.util.Date currDate) {
        GregorianCalendar myCal = new GregorianCalendar();
        GregorianCalendar start = new GregorianCalendar();
        myCal.setTime(currDate);

        int day = myCal.get(Calendar.DAY_OF_MONTH);
        start.set(GregorianCalendar.DAY_OF_MONTH, day);
        int month = myCal.get(Calendar.MONTH);
        start.set(GregorianCalendar.MONTH, month);
        // use 1901 since not a leap year
        start.set(GregorianCalendar.YEAR, 1901);
        int numDays = start.get(GregorianCalendar.DAY_OF_YEAR);
        //System.out.println("***" + numDays);
        return numDays;
    }

    public static int getYear(java.util.Date date) {
        GregorianCalendar myCal = new GregorianCalendar();
        myCal.setTime(date);
        int year = myCal.get(Calendar.YEAR);
        return year;
    }

    public static java.util.Date addToDate(java.util.Date date, int dateDield, int value) {
        GregorianCalendar myCal = new GregorianCalendar();
        myCal.setTime(date);
        myCal.add(dateDield, value);
        return new java.util.Date(myCal.getTimeInMillis());
    }

    public static boolean isValidDate(String inDate) {
        try {
            parseDateFormat.parse(inDate.trim());
        } catch (ParseException pe) {
            return false;
        }
        return true;
    }
   

}

