package csis626;
import java.rmi.*;
import java.util.*;

/**
   This bean authenticates the user
*/
public class LoginBean
{
   private boolean isLoginSuccessful;
   private DBInterface database;
   private String stud_id;
   private String password;
   private String stud_degree;   
   private String personalInfo;
   private String transcript_cnum;
   private String transcript_date;
   private String degree_eval;
   private String requirements;
   private String output_message;
   private String displayCourses;
   private String plannedCourses;
   private String course;
   private String semester;
   private String delete_course;
   private String sched_degree_eval;
   private Vector planned_courses;
   private Vector prereq_courses;
   private Vector courses_not_taken;
   private Vector display_courses;
   private Vector rem_req_courses;
   private Vector rem_opt_courses;

   /**
      Constructor
   */
   public LoginBean()
   {
      isLoginSuccessful = false;
      output_message = "";
      sched_degree_eval = "";
   }

   /**
      Read-only stud_id property
      @return the Student ID
   */
   public String getStud_id()
   {
      return stud_id;
   }

   /**
      Write-only stud_id property
      @param input_id the Student ID
   */
   public void setStud_id(String input_id)
   {
      stud_id = input_id;
   }

   /**
      Read-only password property
      @return the Passwprd
   */
   public String getPassword()
   {
      return password;
   }

   /**
      Write-only password property
      @param input_password the Student password
   */
   public void setPassword(String input_password) throws Exception
   {
      password = input_password;

      /* Authenticate user */
      authenticate();

   } /* End method setPassword */

   /**
      Read-only output_message property
      @return output_message string of output messages
   */
   public String getOutput_message()
   {
      return output_message;
   }
   
   /**
      Write-only output_message property
      @param input_msg the output message to report
   */
   public void setOutput_message(String input_msg)
   {
      output_message = input_msg;
   }

   /**
      Read-only sched_degree_eval property
      @return sched_degree_eval string that describes whether
      current planned schedule meets degree requirements
   */
   public String getSched_degree_eval()
   {
      return sched_degree_eval;
   }

   /**
      Read-only isLoginSuccessful property
      @return output_message with regards to whether url link is valid
   */
   public boolean getIsLoginSuccessful()
   {
      return isLoginSuccessful;
   }

   /**
      Read-only personalInfo property
      @return Student Personal Info in HTML string
   */
   public String getPersonalInfo()
   {
      return personalInfo;
   }

   /**
      Read-only stud_degree property
      @return Student Degree
   */
   public String getStud_degree()
   {
      return stud_degree;
   }

   /**
      Read-only transcript_cnum property
      @return Student's Transcript in HTML string 
      sorted by course number
   */
   public String getTranscript_cnum()
   {
      return transcript_cnum;
   }

   /**
      Read-only transcript_date property
      @return Student's Transcript in HTML string sorted by date
   */
   public String getTranscript_date()
   {
      return transcript_date;
   }

   /**
      Read-only degree_eval property
      @return Student's Degree Evaluation in HTML string
   */
   public String getDegree_eval()
   {
      return degree_eval;
   }

   /**
      Read-only requirements property
      @return Student GPS requirements in HTML string
   */
   public String getRequirements()
   {
      return requirements;
   }

   /**
      Read-only displayCourses property
      @return courses that can be planned in HTML string
   */
   public String getDisplayCourses()
   {
      return displayCourses;
   }

   /**
      Read-only plannedCourses property
      @return courses that have been planned in HTML string
   */
   public String getPlannedCourses()
   {
      return plannedCourses;
   }

   /**
      Write-only course property
      @param input_course the course that is planned
   */
   public void setCourse(String input_course) throws Exception
   {
      course = input_course;
   } 

   /**
      Write-only semester property
      @param input_semester the semester course is planned
   */
   public void setSemester(String input_semester) throws Exception
   {
      semester = input_semester;
   } 

   /**
      Write-only year property
      @param input_year the year course is planned
   */
   public void setYear(String input_year) throws Exception
   {
      int i;
      int date, date2;
      int prereq_date;
      int course_date;
      int index;
      String sem_str;
      Vector row_vec1, row_vec2;
      Vector row_vec3;


      /* Find out when prereqs for this course was taken */
      prereq_date = 0;
      course_date = Integer.parseInt(input_year);
      course_date *= 10;

      if (semester.equals("Spring"))
         course_date += 1;
      else if (semester.equals("Summer"))
         course_date += 2;
      else if (semester.equals("Fall"))
         course_date += 3;
      else if (semester.equals("Winter"))
         course_date += 4;
      
      /* Prerequisites of course to be added */
      index = prereq_courses.indexOf(course);
      row_vec1 = (Vector) prereq_courses.elementAt(index + 1);
         
      for (i = 0; i < row_vec1.size(); i++)
      {
         row_vec2 = (Vector) row_vec1.elementAt(i);

         switch (row_vec2.size())
         {
            case 1:
            {
               /* Prereq */
               index = planned_courses.indexOf((String) row_vec2.elementAt(0));

               if (index >= 0)
               {           
                  date = Integer.parseInt((String) planned_courses.elementAt(index + 2));

                  if (prereq_date < date)
                     prereq_date = date;
               }
               else
                  date = 0;
               break;
            }
            case 2:
            {
               /* Prereq */
               index = planned_courses.indexOf((String) row_vec2.elementAt(0));
               if (index >= 0)
                  date = Integer.parseInt((String) planned_courses.elementAt(index + 2));
               else
                  date = 0;

               /* Alt prereq */
               index = planned_courses.indexOf((String) row_vec2.elementAt(1));

               if (index >= 0)
                  date2 = Integer.parseInt((String) planned_courses.elementAt(index + 2));
               else
                  date2 = 0;

               /* Take the smaller of the two dates */
               if (date == 0)
                  date = date2;

               if (date2 != 0)
               {
                  if (date2 < date)
                     date = date2;
               }

               if (prereq_date < date)
                  prereq_date = date;

               break;
            }
            default:
               /* Do Nothing */

         } /* End switch statement */
      } /* End for loop for prerequisites */


      if (course_date <= prereq_date)
      {
         date = prereq_date - 1;
         if ((date % 5) == 0)
            sem_str = "Spring";
         else
         {
            date--;
            if ((date % 5) == 0)
               sem_str = "Summer";
            else
            {
               date--;
               if ((date % 5) == 0)
                  sem_str = "Fall";
               else
                  sem_str = "Winter";
            }
         }
         date /= 10;

         output_message = "<B><FONT COLOR=\"#FF0000\">" +
                          course + " needs to be added after " +
                          sem_str + " " + date +
                          "</B></FONT>";
      }
      else
      {
         planned_courses.addElement(course);      
         row_vec1 = new Vector();
         row_vec1.addElement(semester);
         row_vec1.addElement(input_year);            
         planned_courses.addElement(row_vec1);
         planned_courses.addElement(Integer.toString(course_date));

         parseDisplayCourses();
         parsePlannedCourses();
         parseSchedDegreeEval();
         output_message = course + " added successfully";
      }
   } /* End method setYear */

   /**
      Write-only delete_course property
      @param input_course the course to delete
   */
   public void setDelete_course(String input_course) throws Exception
   {
      int i, j;
      int index;
      int index2;
      Vector row_vec1, row_vec2;
      Vector temp_not_taken;


      output_message = "Deleted: " + input_course;

      /* Create temp_not_taken list */
      temp_not_taken = (Vector) courses_not_taken.clone();

      /* Delete course from planned_courses list             */
      /* Delete the semester, year & date associated with it */
      index = planned_courses.indexOf(input_course);
      planned_courses.removeElementAt(index);
      planned_courses.removeElementAt(index);
      planned_courses.removeElementAt(index);

      /* Subtract planned_courses from temp_not_taken list */
      for (i = 0; i < planned_courses.size(); i+=3)
         temp_not_taken.removeElement((String) planned_courses.elementAt(i));

      /* Delete classes that use this course as prereq */      
      for (i = 0; i < planned_courses.size(); i+=3)
      {
         /* Prerequisites of course from planned_courses list */
         index = prereq_courses.indexOf((String) planned_courses.elementAt(i));
         row_vec1 = (Vector) prereq_courses.elementAt(index + 1);

         /* Check for prerequisites */
         for (j = 0; j < row_vec1.size(); j++)
         {
            row_vec2 = (Vector) row_vec1.elementAt(j);

            switch (row_vec2.size())
            {
               case 1:
               {
                  /* The input course is a prereq for this course */
                  if (input_course.equals((String) row_vec2.elementAt(0)))
                  {
                     output_message = output_message + ", " +
                                      planned_courses.elementAt(i);
                     planned_courses.removeElementAt(i);
                     planned_courses.removeElementAt(i);
                     planned_courses.removeElementAt(i);
                     i -= 3;
                  }

                  break;
               }
               case 2:
               {
                  /* The input course is a prereq for this course */
                  if (input_course.equals((String) row_vec2.elementAt(0)))
                  {
                     /* Need to check if we have alt prereq met */
                     index2 = temp_not_taken.indexOf((String) row_vec2.elementAt(1));
                     /* Alternate prereq is not met */
                     if (index2 >= 0)
                     {
                        output_message = output_message + ", " +
                                      planned_courses.elementAt(i);
                        planned_courses.removeElementAt(i);
                        planned_courses.removeElementAt(i);
                        planned_courses.removeElementAt(i);
                        i -= 3;
                     }
                  }
                  else if (input_course.equals((String) row_vec2.elementAt(1)))
                  {
                     /* Need to check if prereq is met */
                     index2 = temp_not_taken.indexOf((String) row_vec2.elementAt(0));

                     /* Prereq is not met */
                     if (index2 >= 0)
                     {
                        output_message = output_message + ", " +
                                         planned_courses.elementAt(i);
                        planned_courses.removeElementAt(i);
                        planned_courses.removeElementAt(i);
                        planned_courses.removeElementAt(i);
                        i -= 3;
                     }
                  }
                  break;
               }
               default:
                  /* Do Nothing */

            } /* End switch statement */
         } /* End for loop for prerequisites */
      } /* End for loop for planned_courses */
         
      parseDisplayCourses();
      parsePlannedCourses();
      parseSchedDegreeEval();

   } /* End method setDelete_course */

   /**
      Write-only save_course property
      Triggers to save planned_courses into the database on server
      @param ignore_input just a place holder for using bean
   */
   public void setSave_course(String ignore_input) throws Exception
   {
      database.saveCourses(planned_courses);

   } /* End method setSave_course */


   /**
      Parses planned_courses vector list to create
      a HTML string (table) for displaying schedule
   */
   private void parsePlannedCourses() throws Exception
   {
      int i;
      int index;
      int[] temp_array;
      Vector row_vec1;
      Vector temp_vec;

      /* Sort planned_courses */
      temp_vec = new Vector();
      temp_array = new int[planned_courses.size() / 3];

      for (i = 0; i < temp_array.length; i++)
         temp_array[i] = Integer.parseInt((String) planned_courses.elementAt((i*3)+2));

      Arrays.sort(temp_array);

      for (i = 0; i < temp_array.length; i++)      
      {
         index = planned_courses.indexOf(Integer.toString(temp_array[i]), 0);
         while (index >= 0)
         {
            temp_vec.addElement(planned_courses.elementAt(index - 2));
            temp_vec.addElement(planned_courses.elementAt(index - 1));
            temp_vec.addElement(planned_courses.elementAt(index));

            index += 1;
            index = planned_courses.indexOf(Integer.toString(temp_array[i]), index);
            if (index >= 0)
               i++;
         }
      }

      planned_courses = temp_vec;

      plannedCourses = "\n<TABLE BORDER=\"1\" CELLPADDING=\"7\" " +
                       "BORDERCOLOR=\"#800080\">" +
                       "\n<TR>" +
                       "\n<TD BGCOLOR=\"#D8BFD8\"><B>Course Number</B></TD>" +
                       "\n<TD BGCOLOR=\"#D8BFD8\"><B>Semester</B></TD>" +
                       "\n<TD BGCOLOR=\"#D8BFD8\"><B>Year</B></TD>" +
                       "\n<TD> </TD>" +
                       "\n</TR>";
   
      /* Parse into HTML String Planned Classes */
      for (i = 0; i < planned_courses.size(); i+=3)
      {
         row_vec1 = (Vector) planned_courses.elementAt(i+1);
         plannedCourses = plannedCourses + "\n<TR> \n<TD>" +
                          (String) planned_courses.elementAt(i) +
                          "</TD> \n<TD>" +
                          (String) row_vec1.elementAt(0) +
                          "</TD> \n<TD>" +
                          (String) row_vec1.elementAt(1) +
                          "</TD> \n<TD VALIGN=\"middle\">" +
                          "<FORM ACTION=\"planning.jsp\" METHOD=\"POST\">" +
                          "<INPUT TYPE=\"hidden\" " + 
                          "NAME=\"del_course\" " +
                          "VALUE=\"" + (String) planned_courses.elementAt(i) +
                          "\"> " +
                          "<INPUT TYPE=\"submit\" " +
                          "VALUE=\"DELETE\"/>" +
                          "</FORM>" +
                          "</TD> \n</TR>";
      }

   } /* End method parsePlannedCourses */

   /**
      Parses courses_not_taken vector list to create
      display_courses list into a HTML string
      for list of courses with which to schedule 
   */
   private void parseDisplayCourses() throws Exception
   {
      int i, j;
      int index;
      String display_str;
      String course_str;
      Vector row_vec1, row_vec2;
      Vector temp_not_taken;

   
      /* Create temp_not_taken list */
      temp_not_taken = (Vector) courses_not_taken.clone();

      /* Subtract planned_courses from temp_not_taken list */
      for (i = 0; i < planned_courses.size(); i+=3)
         temp_not_taken.removeElement((String) planned_courses.elementAt(i));

      /* Create display_courses list */
      display_courses = (Vector) temp_not_taken.clone();

      /* Subtract courses that need prereqs that student has not taken */
      for (i = 0; i < temp_not_taken.size(); i++)
      {
         display_str = (String) temp_not_taken.elementAt(i);

         index = prereq_courses.indexOf(display_str);
         row_vec1 = (Vector) prereq_courses.elementAt(index + 1);

         /* Check for prerequisites */
         for (j = 0; j < row_vec1.size(); j++)
         {
            row_vec2 = (Vector) row_vec1.elementAt(j);
         
            switch (row_vec2.size())
            {
               case 1:
               {
                  course_str = (String) row_vec2.elementAt(0);

                  /* If prereq is in courses_not taken    */
                  /* drop course from display_course list */
                  if (temp_not_taken.indexOf(course_str) >= 0)
                     display_courses.removeElement(display_str);
                  break;
               }
               case 2:
               {
                  course_str = (String) row_vec2.elementAt(0);

                  /* If prereq is in courses_not taken */
                  /* check alternate prereq            */
                  if (temp_not_taken.indexOf(course_str) >= 0)
                  {
                     course_str = (String) row_vec2.elementAt(1);
                     /* Alternate prereq is in courses not taken */
                     /* drop course from display_course list     */
                     if (temp_not_taken.indexOf(course_str) >= 0)
                        display_courses.removeElement(display_str);
                  }   
                  break;
                }
                default:
                   /* Do Nothing */
            }
         } /* End for loop to check prerequisites are met */

      } /* End for loop for each course in display_course list  */

      /* Parse into HTML String Courses with which to plan schedule */            
      displayCourses = "";
      for (i = 0; i < display_courses.size(); i++)
      {
         course_str = (String) display_courses.elementAt(i);

         displayCourses = displayCourses + 
                          "<OPTION VALUE=\"" + course_str +
                          "\">" + course_str + 
                          "</OPTION>";
      }

   } /* End method parseDisplayCourses */

   /**
      Parses planned_courses vector to determine
      if it meets the degree requirements
   */
   private void parseSchedDegreeEval() throws Exception
   {
      int i;
      int index, index2;
      int met_count;
      int rem_opt_count;
      int req_count;
      int opt_count;
      String req_string;
      String opt_string;
      Vector temp_vec;

      
      sched_degree_eval = "Current Schedule does not meet "
                          + stud_degree + " degree requirements";

      req_string = "<BR>Still require: ";
      met_count = 0;

      /* Check against rem_req_courses */
      req_count = 0;
      for (i = 0; i < rem_req_courses.size(); i+=2 )
      {
         index = planned_courses.indexOf((String) rem_req_courses.elementAt(i));
         if (index < 0)
         {
            /* Check for alternate requirement */
            temp_vec = (Vector) rem_req_courses.elementAt(i+1);
            if (temp_vec.size() > 0)
            {
               index2 = planned_courses.indexOf((String) temp_vec.elementAt(0));
               if (index2 < 0)
               {
                  req_string = req_string + (String) rem_req_courses.elementAt(i) + 
                               " or " + (String) temp_vec.elementAt(0) + ", " ;
               }
               else
                  req_count++;

            }
            else
               req_string = req_string + (String) rem_req_courses.elementAt(i) + ", ";
         }
         else
            req_count++;
      }
   
      /* Taken all the required courses for the degree */
      if (req_count == (rem_req_courses.size() / 2))
      {
         req_string = "";
         met_count++;
      }

      /* Check against rem_opt_courses */
      opt_count = 0;
      rem_opt_count = Integer.parseInt((String) rem_opt_courses.elementAt(0));
      for (i = 1; i < rem_opt_courses.size(); i++ )
      {      
         index = planned_courses.indexOf((String) rem_opt_courses.elementAt(i));

         if (index >= 0)
            opt_count++;

         /* Taken the number of optional courses required for degree */
         if (opt_count == rem_opt_count)
         {
            met_count++;
            break;
         }
      }

      if (opt_count == rem_opt_count)
         opt_string = "";
      else
      {
         opt_string = "<BR>Still need to take " + 
                      (rem_opt_count - opt_count) +
                      " optional courses";
      }

      /* Met all requirements for degree */
      if (met_count == 2)
      {
         sched_degree_eval = "<B>All requirements have been met for " +
                             stud_degree + " degree requirements</B>";
      }
      else
      {
         sched_degree_eval = sched_degree_eval + req_string + opt_string;
      }


   } /* End method parseSchedDegreeEval */

   /**
      Authenticates user
   */
   public void authenticate() throws Exception
   {
      try
      {
         /* Connect to Remote object */
         database = (DBInterface) Naming.lookup("//localhost/MyDatabase");
         
         /* Authenticate user */
         if ( database.isValidUser(stud_id, password) )
         {
            isLoginSuccessful = true;
            personalInfo = database.getPersonalInfo();
            stud_degree = database.getDegree();
            transcript_cnum = database.getTranscript_cnum();
            transcript_date = database.getTranscript_date();
            degree_eval = database.getDegreeEval();
            requirements = database.getRequirements();
            planned_courses = database.getPlanned();
            prereq_courses = database.getPrereq();
            courses_not_taken = database.getNotTaken(); 
            rem_req_courses = database.getRemainReqCourses();
            rem_opt_courses = database.getRemainOptCourses();

            parseDisplayCourses();
            parsePlannedCourses();
            parseSchedDegreeEval();
         }
         else
         {
            isLoginSuccessful = false;
         }
      }
      catch (Exception e)
      {
         output_message = "Error occurred: " + e;
      }

   } /* End method authenticate */


} /* End class LoginBean */
