import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.Scanner;
/**
 * plainDate is a way to read the date information from an assignment.
 * 
 * @author Fred Kral
 * @version 1.3
 */
 /*
  Help:
   http://www.mkyong.com/java/java-date-and-calendar-examples/
   http://www.vogella.com/tutorials/JavaDateTimeAPI/article.html
 */
 
public class plainDate {
   
//   private static final int YEAR_DEFAULT = 2014;

   int day = 0;
   int month = 0; 
   int year = 0; 
   boolean validDate = false;
   Calendar calendar;
   SimpleDateFormat sdf;
   
   public plainDate () {
      this(0, 0, 0);
   }
   /** plainDate(line, year) uses a string in this format:  09 Dec, Tue */
   public plainDate (String dayMonthLine, int year) {
      this(parseDay(dayMonthLine), parseMonth(dayMonthLine), year);
   }

   /** plainDate with a non-numerical month
    * @param monthString is of the format: Dec
    */
   public plainDate (int day, String monthString, int year) {
      this(day, convertDate(monthString), year);
   }
   
   /** plainDate collects all the calendar data with functions that suit our input file
    * @param day 1-31
    * @param month 1-12
    * @param year for example 2015
    */
   public plainDate (int day, int month, int year) {
      this.day = day;
      this.month = month;  // months numbered 1 to 12
      this.year = year;
      this.validDate = month >= 1 && month <= 12 && day >=1 && day <= 31;
   
      sdf = new SimpleDateFormat("MMM dd");
      calendar = new GregorianCalendar(year, month - 1 , day);
   
   }
   
   // Very important: is this date good or not?
   public boolean getValidDate(){
      //validDate = month >= 1 && month <= 12 && day >=1 && day <= 31;
      return validDate;
   }
   public int getDay(){
      return day;
   }
   public int getMonth(){
      return month;
   }
   public int getYear(){
      return year;
   }
   //public void setYear(int year){
   //   this.year = year;
   //}
   
   public Calendar getCalendar() {
      return calendar;
   }
   
   public boolean equals(plainDate pDate){
      return calendar.equals(pDate.getCalendar());
   }
   
   public int getDayOfWeekFromMonday() { // Monday = 1, Tuesday = 2
      return -1 + calendar.get(Calendar.DAY_OF_WEEK);
   }
   
   public String getWeekdayName () {
      return new SimpleDateFormat("EE").format(calendar.getTime());
   }
   
   public int differenceInDaysInclusive (plainDate pDate) {
      return 1 + (int) daysBetween( calendar, pDate.getCalendar() );  // this date has to be before pDate
   }

   /* Using Calendar to count days */  
   public static long daysBetween(Calendar startDate, Calendar endDate) {  
   //assert: startDate must be before endDate  
      Calendar date = (Calendar) startDate.clone();  
      long daysBetween = 0;  
      while (date.before(endDate)) {  
         date.add(Calendar.DAY_OF_MONTH, 1);  
         daysBetween++;  
      }  
      return daysBetween;  
   } 
   
   
   /** Return a day in the future (or past) counting by days 
   */
   public plainDate addDays (int numDays) {
      
      //add days
      calendar.add(Calendar.DAY_OF_MONTH, numDays);
      //System.out.println("Date : " + sdf.format(calendar.getTime()));
      
      plainDate pDate = 
         new plainDate( calendar.get(Calendar.DAY_OF_MONTH),
                        calendar.get(Calendar.MONTH) + 1, 
                        calendar.get(Calendar.YEAR) );
                        
      // subtract days so as not to change this date
      calendar.add(Calendar.DAY_OF_MONTH, -numDays);
      
      return pDate;
   }
   /** sysPrint
   @param printIt - Does it produce printout?
   @return Returns a printable String, but is it really?
   */
   public String sysPrint(boolean printIt){
      if (printIt) {
         String outString = sdf.format(calendar.getTime());
         System.out.print(outString);
         //if (outstring.length() < 6) System.out.print(" ");
         //System.out.print("    ");
         //System.out.print(month + "/" + day + "/" + year);
      }
      return sdf.format(calendar.getTime());
   }
   
   public static int parseDay (String line){
      Scanner sc = new Scanner(line);
      if (sc.hasNextInt()){
         return sc.nextInt();
      }
      return 0;
   }
   
   public static String parseMonth (String line){
      Scanner sc = new Scanner(line);
      if (sc.hasNextInt()){
         sc.nextInt();
         if (sc.hasNext()) {
            String month = sc.next();
            int len = month.length();
            if (len == 3) return month;
            if (len >= 4) return month.substring(0,3);
         }
      }
      return "";
   }
   
   
   
   public static int convertDate(String month) {
      int m = 0;
      if (month.equals("Jan")) m = 1; 
      if (month.equals("Feb")) m = 2; 
      if (month.equals("Mar")) m = 3;
      if (month.equals("Apr")) m = 4; 
      if (month.equals("May")) m = 5; 
      if (month.equals("Jun")) m = 6;
      if (month.equals("Jul")) m = 7; 
      if (month.equals("Aug")) m = 8; 
      if (month.equals("Sep")) m = 9;
      if (month.equals("Oct")) m =10; 
      if (month.equals("Nov")) m =11; 
      if (month.equals("Dec")) m =12;
      return m;
   }
   
   
   public plainDate getToday(boolean sysPrint) {
        //getting local time, date, day of week and other details in local timezone
      Calendar localCalendar = Calendar.getInstance(TimeZone.getDefault());
      
      Date currentTime = localCalendar.getTime();
      int currentDay = localCalendar.get(Calendar.DATE);
      int currentMonth = localCalendar.get(Calendar.MONTH) + 1;
      int currentYear = localCalendar.get(Calendar.YEAR);
      int currentDayOfWeek = localCalendar.get(Calendar.DAY_OF_WEEK);
      int currentDayOfMonth = localCalendar.get(Calendar.DAY_OF_MONTH);
      int CurrentDayOfYear = localCalendar.get(Calendar.DAY_OF_YEAR);
   
      day = currentDay;
      month = currentMonth; 
      year = currentYear; 
      calendar = localCalendar;
      validDate = true; //one would hope
   
   
      if (sysPrint) {
         //System.out.println("Current Date and time details in local timezone");
         System.out.print(currentTime);
         System.out.print("  ");
         //System.out.println(currentMonth + "/" + currentDay + "/" + currentYear);
         //System.out.println("Current Date: " + currentTime);
         //System.out.println("Current Day: " + currentDay);
         //System.out.println("Current Month: " + currentMonth);
         //System.out.println("Current Year: " + currentYear);
         //System.out.println("Current Day of Week: " + currentDayOfWeek);
         //System.out.println("Current Day of Month: " + currentDayOfMonth);
         //System.out.println("Current Day of Year: " + CurrentDayOfYear);
      }
      
      plainDate pDate = new plainDate(currentDay, currentMonth, currentYear);
      
      if (sysPrint) {
         System.out.print("    ");
         pDate.sysPrint(true); 
         System.out.println();
      }
      
      return pDate;
   }

}// END class