
class Appointment {

	depend java.text.SimpleDateFormat;
    
	AppStatus {
		Booked {
				noShow(Customer c) / {addNoShow(c);} -> Final;
				
				cancel(String currentDate, String sysDate) [canCancel(currentDate, sysDate)] -> Final;
				cancel(String currentDate, String sysDate) [!canCancel(currentDate, sysDate)] / {rejectCancel();} -> Booked;
				
				update(List<Service> newOptServices, List<TimeSlot> timeSlots) [canUpdate()] / {updateApp(newOptServices, timeSlots);} -> Booked;
				update(List<Service> newOptServices, List<TimeSlot> timeSlots) [!canUpdate()] / {rejectUpdate();} -> Booked;
				
				start -> InProgress;
		}
		
		InProgress {
		
			start -> InProgress;
			
			update(List<Service> newOptServices, List<TimeSlot> timeSlots) [canUpdate()] / {updateApp(newOptServices, timeSlots);} -> InProgress;
			update(List<Service> newOptServices, List<TimeSlot> timeSlots) [!canUpdate()] / {rejectUpdate();} -> InProgress;
            
			noShow(Customer c) / {rejectNoShow(c);} -> InProgress;
			
			end -> Final;
		}
	}

	private void addNoShow(Customer c) {
		c.setNoShowCount(c.getNoShowCount() + 1);
	}
	
	private void rejectUpdate() {

	}
  
	private void rejectCancel() {
	    throw new RuntimeException("Cannot cancel an appointment on the appointment date");
	}
	
	private void rejectNoShow(Customer c) {
		throw new RuntimeException("Cannot register a no-show since the appointment has already started");
	}
	
	private boolean canUpdate() {
	  return true;
	}
	  
	private boolean canCancel(String currentDate, String sysDate) {
		return !currentDate.equals(sysDate);
	}
	
	private void updateApp(List<Service> newOptServices, List<TimeSlot> timeSlots){
	   if(newOptServices.size() == 0) {
			// updating existing services of the app
			// make sure when check invalid before not failing because overlapping with existing services
			for(int i=0;i<this.getServiceBookings().size();i++) {
				Service s = this.getServiceBooking(i).getService();
				// might be dangerous to do this but it should work
				// deletes the time slot and the associated service booking and re-create it after
				this.getServiceBooking(i).getTimeSlot().delete();
				
				new ServiceBooking(s,timeSlots.get(i), this);
			}
		} else {
			// adding new services to the app
			for(int i = 0; i< newOptServices.size();i++) {
				new ServiceBooking(newOptServices.get(i), timeSlots.get(i), this);
			}
		}
  }
}