// Complete App from EasyApp
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;

 public class Dates extends EasyApp     // EasyApp contains IBIO + standard constructor stuff
 { public static void main(String[] args)  
   {  new Dates(); }                    // Instantiate an object = start the program
   
   //--- Create Components -------------------------------------------
   Button     bMakeYear   = addButton("Make Year",20,30,100,30,this);
   Button     bSave       = addButton("Save File",20,60,100,30,this);
   Button     bLoad       = addButton("Load File",20,90,100,30,this);
   Button     bSearch     = addButton("Search",20,120,100,30,this);
   Button     bInstruct   = addButton("Instructions",360,30,100,20,this);
   TextArea   aInstruct   = addTextArea("",360,50,220,300,this);
   Label      lEvent      = addLabel("Event",150,60,50,30,this);
   TextField  tEvent      = addTextField("",200,60,150,30,this);
   List       lCalendar   = addList("",150,90,400,300,this);
   Choice     cMonths     = addChoice("",20,160,100,30,this);

   final static Color NICEBLUE = new Color(160,192,255);
   String[] weekdays = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
   String[] months = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};       
   
   //--- Constructor - adjust components, initialize variables -------
   public Dates()
   {  aInstruct.setText(
         "Use [Make Year] to fill in \n" +
         "all the dates for an entire year.\n\n" +
         "Then type the name of an event\n" +
         "in the small text box.\n" +
         "Click on the corresponding date\n" +
         "to write the event into that date.\n" +
         "Notice that recurring events \n\n" +
         "like meetings can be added \n" +
         "many times by clicking\n" +
         "on several different dates.\n\n" +
         "Use the [Save] and [Load] buttons\n" +
         "to save into a text file\n" +
         "and later load it back in."
         );
      aInstruct.setVisible(false);   
      
      aInstruct.setBackground(NICEBLUE);   
      lEvent.setBackground(NICEBLUE);
      setBackground(NICEBLUE);
      
      cMonths.add("-- Months --");
      for (int c=0; c < 12; c = c+1)
      { cMonths.add( months[c] );}
   }

   //--- Handle Button clicks and TextField [enter] key ------
   public void actionPerformed(ActionEvent evt)
   {  
      Object source = evt.getSource();

      if (source == bMakeYear)
      {   makeYear(); }
      else if (source == bInstruct)
      {   toggleInstructions();  }
      else if (source == bSave)
      {   save(); }
      else if (source == bLoad)
      {   load(); }
      else if (source == bSearch)
      {   search(); }
   }   
   
   //--- Handle List and Checkbox clicks ---------------------
   public void itemStateChanged(ItemEvent evt)
   {  
       Object source = evt.getSource();
       
       if (source == lCalendar)
       {   addEvent();  }
       else if (source == cMonths)
       {   findMonth(); }    
   }   
   
   //--- Draw title at top of page --------------------------------
   public void paint(Graphics g)
   {   
       g.setColor(Color.black);
       g.setFont(new Font("Arial",0,24));
       g.drawString("Dates Database",150,50);
   }
   
   //--- Toggle visibility of Instructions TextArea  ---
   public void toggleInstructions()    
   {
       if (aInstruct.isVisible())            
       { aInstruct.setVisible(false); }
       else
       { aInstruct.setVisible(true); }
   }
   
   //--- Fill calendar list with an entire year of dates ---
   public void makeYear()
   {   
       String firstday = input("Type the abbreviation for the first weekday of the year:\n" +
                               "   Sun, Mon, Tue, Wed, Thu, Fri, Sat");

       int w = 0;
       for (int c = 0; c < 7; c = c+1)            // search for day-of-week matching input
       {  
           if ( weekdays[c].equals(firstday) )
           { w = c;}                              // set number of day-of-week = 0...6
       }    

       int[]   maxdays = {31,28,31,30,31,30,31,31,30,31,30,31};

       char   leapyear = inputChar("Is it a leapyear (Y/N)?");
       if ( leapyear =='Y' || leapyear == 'y' )
       { maxdays[1] = 29;}
       
       lCalendar.removeAll();
       int m = 0;
       int d = 0;

       do                                   // count through all 12 months,
       {                                    //  adding each date to the list
           d = d + 1;                       // next day
           if (d > maxdays[m])              // past end-of-month?
           {   
               d = 1;                       // set day back to 1
               m = m + 1;                   // change to next month
           }
           lCalendar.add( months[m] + " " + d + " " + weekdays[w] + "   ");
           w = (w + 1) % 7;                 // next day of week, wrap from 7 to 0
       } while (!(m==11 && d==31) );        // quit after Dec 31
       
   }
   
   //--- Write all dates (whole year) into text file  ---
   public void save()                      
   {   try
       {   
           PrintWriter outFile
              = new PrintWriter(new FileWriter("Dates.txt"));     // open file for writing
           for (int c = 0; c < lCalendar.getItemCount(); c = c+1) // count through whole list
           { outFile.println( lCalendar.getItem(c));}             // print each date
           outFile.close();
       }
       catch (IOException e) { output(e.toString());}          // must handle IO errors,
                                                               // such as write-protected
   }
   
   //--- Load an entire year from text-file into lCalendar list -----
   public void load()
   {
       try
       {   BufferedReader inFile
               = new BufferedReader(new FileReader("Dates.txt"));  // open file for reading

           lCalendar.removeAll();                                  // clear list box
           while ( inFile.ready() )                                // stops at end of file
           {
               String info = inFile.readLine();                    // reads one line of text
               lCalendar.add(info);                                // copy into calendar list
           }
           inFile.close();                                         // close the file
       }
       catch (IOException e) { output(e.toString());}              // handle IO errors, such as
   }                                                               //  file-not-found
   
   //--- Search for an event, as any part of any string in lCalendar ---
   //---   Returns and displays multiple matches -----------------------
   public void search()
   {
       String  target  = input("What are you searching for?");
       String  results = "";
       
       for (int c=0; c < lCalendar.getItemCount(); c = c+1)       // count through calendar list
       {   String info = lCalendar.getItem(c);                    // get one item
           if ( info.indexOf(target) >= 0 )                       // check whether target is
           {   results = results + info + "\n";}                  //   found in info somewhere
       }                                                          // If found, add whole day
                                                                  //   to results
       output(results);                                           // Show results
   }
   
   //--- Append event to date String that was clicked ------
   public void addEvent()
   {
        String info = lCalendar.getSelectedItem();                // Get selected text
        int pos = lCalendar.getSelectedIndex();                   // remember clicked position
        info = info + " | " + tEvent.getText();                   // append event text
        lCalendar.replaceItem(info,pos);                          // write back into list
   }
   
   //--- Find month in lCalendar matching cliked item in cMonths ----
   public void findMonth()
   {
        if (cMonths.getSelectedIndex()>0)
        {   int c = 0;
            while ( c < lCalendar.getItemCount()
                    && !lCalendar.getItem(c).substring(0,3).equals(cMonths.getSelectedItem())
                  )
            { c = c + 1;}

            if ( c < lCalendar.getItemCount() )
            {   
                lCalendar.makeVisible(c);
            }
        }   
   }
 }