package src.hibernatebb.discussion;

import src.hibernatebb.discussion.HibernateUtil;
import src.hibernatebb.discussion.User;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

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

/**
 * 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 src.hibernatebb.discussion.HibernateUtil
 * @see src.hibernatebb.discussion.Post
 * @see src.hibernatebb.discussion.Topic
 * @see src.hibernatebb.discussion.User
 */
public class BoardManager {
	//SessionFactory factory;
	//Configuration cfg;
	
	//BoardManager() {
	//	try {
	//		cfg = new Configuration()
	//			.addClass(src.hibernatebb.discussion.User.class)
	//			.addClass(src.hibernatebb.discussion.Topic.class)
	//			.addClass(src.hibernatebb.discussion.Post.class);
	//		factory = cfg.buildSessionFactory();
	//	} catch (Exception e) {
	//		System.out.println("Hibernate configuration failed:" + e);
	//	}
	//}
	
	
	/**
	 * Gets the full list of Topics
	 * 
	 * @return the list of Topics in the database
	 */	
	public List getTopics() {
		List t;
//		ListIterator lt;
		
		//Session session = factory.openSession();
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			Transaction tx = session.beginTransaction();
					
			t = session.createSQLQuery(
				"SELECT * FROM topics")
				.addEntity(Topic.class)
				.list();
			//t = session.createQuery("from topics").list();
			session.flush();
			
//			lt = t.listIterator();
//			
//			while(lt.hasNext()) {
//				System.out.println((String)lt.next());
//			}
			
			tx.commit();		

		} catch (ObjectNotFoundException e) {
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}

		return t;
	}
	
	
	/**
	 * Compares the password of the supplied user id with
	 * the password on file
	 * @param id the <code>User</code> id
	 * @param password the <code>User</code>'s password
	 * @return boolean of id and password match
	 */
	public boolean checkPassword(String id, String password) {
		User user = loadUser(id);
		if(user == null) {
			return false;
		}
		if (user.getPassword().equals(password)) {
			return true;
		}
		return false;
	}

	/**
	 * Gets <code>User</code> based on id.  If not found returns null.
	 * 
	 * @param id the <code>User</code> id
	 * @return the <code>User</code>
	 */	
	public User loadUser (String id) {
		src.hibernatebb.discussion.User u = new User();
		//Session session = factory.openSession();
		Session session = src.hibernatebb.discussion.HibernateUtil.getSessionFactory().getCurrentSession();

		try{
			Transaction tx = session.beginTransaction();
			
			// one way to load by passing class and id
			//u = new User((User)session.load(User.class,id));
			session.load(u,id);
			session.flush();
			tx.commit();		

		} catch (ObjectNotFoundException e) {
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}

		return u;
	}
	
	/**
	 * Saves <code>User</code>.  If user already exists updates.
	 * 
	 * @param user the <code>User</code>
	 */	
	public void saveUser(User user) throws Exception {
		User newuser;
		
		newuser = loadUser(user.getID());

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		if (newuser==null) {
			// user does not exist
			try{
				Transaction tx = session.beginTransaction();

				session.save(user);
				session.flush();
				tx.commit();		
	
				return;
			} finally {
				//if(session.isOpen()) session.close();
			}
		} else {
			// update user as user already exists
			try{
				Transaction tx = session.beginTransaction();

				session.update(user);
				session.flush();
				tx.commit();		
	
				return;
			} finally {
				//if(session.isOpen()) session.close();
			}			
		}
	}
	
	/**
	 * Removes <code>User</code>. Does not remove <code>Topic</code> or 
	 * orphaned <code>Post</code>'s.  This is left to the developer.
	 * Don't make orphans!
	 * 
	 * @return the removed <code>User</code>
	 * @param id the <code>User</code>'s id
	 */	
	public User removeUser(String id) throws Exception {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		User user = new User();
		
		try{
			Transaction tx = session.beginTransaction();
			
			// other way to load by passing object and id
			session.load(user,id);
			session.delete(user);
			
			session.flush();
			tx.commit();		

			return user;
		} catch (Exception e) {
			//catching for when user does not exist in db to be removed
			//this is a poor way to handle the exception
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}
		
	}

	/**
	 * Gets <code>Post</code> based on id.  If not found returns null.
	 * 
	 * @param the <code>Post</code> id
	 * @return the <code>Post</code>
	 */	
	public Post loadPost (Long id) {
		Post p = new Post();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		try{
			Transaction tx = session.beginTransaction();
			
			// one way to load by passing class and id
			//u = new User((User)session.load(User.class,id));
			session.load(p,id);
			session.flush();
			tx.commit();		

		} catch (ObjectNotFoundException e) {
			return null;
		} catch (IllegalArgumentException e) {
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}

		return p;
	}
	
	/**
	 * Saves <code>Post</code>.  If the post already exists updates.
	 * 
	 * @param p the <code>Post</code>
	 */	
	public void savePost(Post p) throws Exception {
		Post newpost;
		
		newpost = loadPost(p.getID());

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		if (newpost==null) {
			// post does not exist
			try{
				Transaction tx = session.beginTransaction();

				session.save(p);
				session.flush();
				tx.commit();		
	
				return;
			} finally {
				//if(session.isOpen()) session.close();
			}
		} else {
			// update user as user already exists
			try{
				Transaction tx = session.beginTransaction();

				session.update(p);
				session.flush();
				tx.commit();		
	
				return;
			} finally {
				//if(session.isOpen()) session.close();
			}			
		}
	}
	
	/**
	 * Removes <code>Post</code>. Does not remove <code>User</code> or 
	 * orphaned <code>Topic</code>'s.  This is left to the developer.
	 * Don't make orphans!
	 * 
	 * @return the removed <code>Post</code>
	 * @param id the <code>Post</code>'s id
	 */	
	public Post removePost(String id) throws Exception {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		Post p = new Post();
		
		try{
			Transaction tx = session.beginTransaction();
			
			// other way to load by passing object and id
			session.load(p,id);
			session.delete(p);
			
			session.flush();
			tx.commit();		

			return p;
		} catch (Exception e) {
			//catching for when user does not exist in db to be removed
			//this is a poor way to handle the exception
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}
		
	}

	/**
	 * Gets <code>Topic</code> based on id.  If not found returns null.
	 * 
	 * @param the <code>Topic</code> id
	 * @return the <code>Topic</code>
	 */	
	public Topic loadTopic (String id) {
		Topic t = new Topic();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			Transaction tx = session.beginTransaction();
			
			// one way to load by passing class and id
			//u = new User((User)session.load(User.class,id));
			t = new Topic((Topic)session.load(Topic.class,id));
			session.flush();
			
			//t.setPosts(session.find("from posts as p where p.topicID = '" + id +"'"));
			
			tx.commit();		

		} catch (ObjectNotFoundException e) {
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}

		return t;
	}
	
	/**
	 * Saves <code>Topic</code>.  If Topic already exists updates.
	 * 
	 * @param Topic the <code>Topic</code>
	 */	
	public void saveTopic(Topic t) throws Exception {
		Topic newtopic;
		
		newtopic = loadTopic(t.getID());

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		if (newtopic==null) {
			// user does not exist
			try{
				Transaction tx = session.beginTransaction();

				session.save(t);
				session.flush();
				tx.commit();		
	
				return;
			} finally {
				//if(session.isOpen()) session.close();
			}
		} else {
			// update user as user already exists
			try{
				Transaction tx = session.beginTransaction();

				session.update(t);
				session.flush();
				tx.commit();		
	
				return;
			} finally {
				//if(session.isOpen()) session.close();
			}			
		}
	}
	
	/**
	 * Removes <code>Topic</code>. Does not remove <code>User</code> or 
	 * orphaned <code>Post</code>'s.  This is left to the developer.
	 * Don't make orphans!
	 * 
	 * @return the removed <code>Topic</code>
	 * @param id the <code>Topic</code>'s id
	 */	
	public Topic removeTopic(String id) throws Exception {
		Topic t = new Topic();

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			Transaction tx = session.beginTransaction();
			
			// other way to load by passing object and id
			session.load(t,id);
			session.delete(t);
			
			session.flush();
			tx.commit();		

			return t;
		} catch (Exception e) {
			//catching for when user does not exist in db to be removed
			//this is a poor way to handle the exception
			return null;
		} finally {
			//if(session.isOpen()) session.close();
		}
		
	}

	
}

