package com.gmscheduler.model;

import java.util.List;
import java.util.LinkedList;
import java.util.ListIterator;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.gmscheduler.model.HibernateUtil;

/**
 * The DatabaseManager class handles all calls to the hibernate database
 * for manageing the objects that are stored within it
 * @author Peter Deschere
 * @author Rebecca Beale
 * @author Jason Fillo
 * @version 1.0
 * @see <a>http://www.hibernate.org</a>
 * @see com.gmscheduler.model.HibernateUtil
 */
public class DatabaseManager {
	/**
	 * Stores a Timeframe in a hibernate database
	 * @param t	the timeframe to be stored
	 * @return	the timeframe which was stored
	 */
	private Timeframe storeTimeframe(Timeframe t) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		session.save(t);
		tx.commit();		
		return t;
		}
	
	/**
	 * Stores a Person in a hibernate database
	 * @param p	the person to be stored
	 * @return	the person which was stored
	 */
	public Person storePerson(Person p) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		session.save(p);
		tx.commit();		
		return p;
		}

	/**
	 * Stores a Schedule in a hibernate database
	 * @param s	the schedule to be stored
	 * @return	the schedule which was stored
	 */
	public Schedule storeSchedule(Schedule s) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		session.save(s);
		tx.commit();

		s.updateTimeframeid();
		
		LinkedList<Timeframe> sched = s.getSchedule();
		ListIterator sli = sched.listIterator();
		
		while(sli.hasNext()) {
			storeTimeframe((Timeframe)sli.next());
		}
		
		return s;
		}

	/**
	 * loads a <code>Timeframe</code> in a hibernate database
	 * @param id	the <code>Timeframe</code> id to be loaded
	 * @return	the <code>Timeframe</code> which was loaded
	 */
	public Timeframe loadTimeframeById(Long id) {
		Timeframe tf;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();

		tf = new Timeframe((Timeframe)session.load(Timeframe.class,id));

		tx.commit();

		return tf;
	}

	/**
	 * loads a <code>Person</code> in a hibernate database
	 * @param id	the <code>Person</code> id to be loaded
	 * @return	the <code>Person</code> which was loaded
	 */
	public Person loadPersonById(Long id) {
		Person p;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();

		p = new Person((Person)session.load(Person.class,id));

		tx.commit();

		return p;
	}

	/**
	 * loads a <code>Person</code> in a hibernate database
	 * @param name	the <code>Person</code>'s name to be loaded
	 * @return	the <code>Person</code> which was loaded
	 */
	public Person loadPersonByName(String name) {
		Person p = new Person();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		List result = session.createQuery(
				"from Person as person " +
					"where person.name = '" + name + "'").list();
		tx.commit();

		ListIterator lr = result.listIterator();
		
		if (lr.hasNext()) { p = new Person((Person)lr.next()); }
		
		return p;
	}

	/**
	 * loads a list of <code>Schedule</code>s in a hibernate database
	 * @param name	the <code>Person</code>'s name to be loaded
	 * @return	the <code>Schedule</code>s
	 */
	public List loadScheduleByPersonName(String name) {
		List allsched = new LinkedList();
		Person p = new Person();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		List result = session.createQuery(
				"from Person as person " +
					"where person.name = '" + name + "'").list();
		tx.commit();

		ListIterator lr = result.listIterator();
		
		if (lr.hasNext()) { p = new Person((Person)lr.next()); }
		
		session = HibernateUtil.getSessionFactory().getCurrentSession();
		tx = session.beginTransaction();
		List result2 = session.createSQLQuery(
		"SELECT * FROM Schedule WHERE personid=" + p.getId())
		.addEntity(Schedule.class)
		.list();
		tx.commit();
		
		ListIterator lr2 = result2.listIterator();
		while (lr2.hasNext()){
			allsched.add(new Schedule(loadScheduleById(((Schedule)lr2.next()).getId())));
		}
		
		return allsched;
	}
	
	/**
	 * loads a list of all <code>Schedule</code>s in a hibernate database
     *
	 * @return	the <code>Schedule</code>s
	 */
	public List loadAllSchedules() {
		List newres = new LinkedList();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		List allsched = session.createQuery(
		"FROM Schedule").list();
		
		tx.commit();		
		
		ListIterator lr = allsched.listIterator();
		Schedule s;
		while(lr.hasNext()) {
			s = new Schedule(loadScheduleById(((Schedule)lr.next()).getId()));
			newres.add(s);
		}
		
		return newres;
	}
	
	
	/**
	 * loads a <code>Schedule</code> in a hibernate database
	 * @param id	the <code>Schedule</code> id to be loaded
	 * @return	the <code>Schedule</code> which was loaded
	 */
	public Schedule loadScheduleById(Long id) {
		Schedule s;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();

		s = new Schedule((Schedule)session.load(Schedule.class,id));
		tx.commit();

		ListIterator lils = loadTimeframesBySchedId(s.getId()).listIterator();
		
		while (lils.hasNext()) {
			s.addTimeframe((Timeframe)lils.next());
		}
		
		return s;
	}

	/**
	 * loads a list of <code>Timeframe</code>s in a hibernate database
	 * @param id	the <code>Schedule</code> id of the <code>Timeframe</code>s to be loaded
	 * @return	the list of <code>Timeframe</code>s which was loaded
	 */
	public List loadTimeframesBySchedId(Long id) {		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();
		List result = session.createQuery(
				"from Timeframe as timeframe " +
					"where timeframe.scheduleid = " + id.toString()).list();
		tx.commit();

		return result;
	}
	
	/**
	 * Deletes a <code>Person</code> in a hibernate database
	 * @param p	the <code>Person</code> to be deleted
	 */
	public void deletePerson(Person p) {
		p = loadPersonById(p.getId());
		if (p.isEmpty()) {
			// do nothing
		} else {
			Session session = HibernateUtil.getSessionFactory().getCurrentSession();
			Transaction tx = session.beginTransaction();
		
			session.delete(p);
			tx.commit();
		}
	}
	
	/**
	 * Deletes a <code>Timeframe</code> in a hibernate database
	 * @param t	the <code>Timeframe</code> to be deleted
	 */
	public void deleteTimeframe(Timeframe t) {
		//System.out.println(":::Tframe:" + t.getId().toString() + " " + t.toString());
		t = loadTimeframeById(t.getId());
		//System.out.println(":::Tframe:" + t.getId().toString() + " " + t.toString());
		if (t.isEmpty()) {
			// do nothing
		} else {

			Session session = HibernateUtil.getSessionFactory().getCurrentSession();
			Transaction tx = session.beginTransaction();
			session.delete(t);
			tx.commit();
		}
	}

	/**
	 * Deletes a <code>Schedule</code> in a hibernate database
	 * @param s	the <code>Schedule</code> to be deleted
	 */
	public void deleteSchedule(Schedule s) {
		ListIterator ls = s.getSchedule().listIterator();
		
		while (ls.hasNext()) {
			deleteTimeframe((Timeframe)ls.next());
		}

		s = loadScheduleById(s.getId());
		if (s.isEmpty()) {
			// do nothing
		} else {
		
			Session session = HibernateUtil.getSessionFactory().getCurrentSession();
			Transaction tx = session.beginTransaction();
			session.delete(s);
			tx.commit();
		}
	}

}
