package ub.scp2.daoImpl;

import java.io.InputStream;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import ub.scp2.dao.TaskDao;
import ub.scp2.entities.Subject;
import ub.scp2.entities.Task;
import ub.scp2.entities.Test;
import ub.scp2.entities.User;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;

/**
 * TaskDaoImpl.java -this class implements the TaskDao. This is the Data Acces Object of the Task entity
 * 
 *
 */
public class TaskDaoImpl implements TaskDao, java.io.Serializable {
	SessionFactory sessionFactory;
	
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	/**
	 * Retrieve a task list with all task
	 */
	public List<Task> getTasks(){
		 Session session = sessionFactory.getCurrentSession();
		 try{
			 return session.createQuery( "FROM Task" ).list();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
		return null;
	}
	
	/**
	 * Retrieve a task list with active task by user
	 */
	public List<Task> getActiveTasksByUser(User user){
		 Session session = sessionFactory.getCurrentSession();

		 try{
			 Criteria criteria = session.createCriteria(Task.class);
			 criteria.add(Restrictions.eq("user", user));
			 criteria.add(Restrictions.ge("endDate", new Date()));
			 criteria.addOrder(Order.asc("endDate"));
			 return criteria.list();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
		return null;
	}
	
	/**
	 * Retrieve a task list with expired task by user
	 */
	public List<Task> getExpiredTasksByUser(User user){
		 Session session = sessionFactory.getCurrentSession();

		 try{

			 Criteria criteria = session.createCriteria(Task.class);
			 criteria.add(Restrictions.eq("user", user));			 
			 criteria.add(Restrictions.lt("endDate", new Date()));
			 criteria.addOrder(Order.asc("endDate"));
			 return criteria.list();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
		return null;
	}
	
	/**
	 * Save task in database
	 */
	public void saveTask(Task task){
		 Session session = sessionFactory.getCurrentSession();
		 try{
			 session.save(task);
			 session.flush();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
	}
	
	/**
	 * Delete task in database
	 */
	public void deleteTask(Task task){
		 Session session = sessionFactory.getCurrentSession();
		 try{
			 session.delete(task);
			 session.flush();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
	}
	
	/**
	 * Update task in database
	 */
	public void updateTask(Task task){
		 Session session = sessionFactory.getCurrentSession();
		 try{
			 session.update(task);
			 session.flush();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
	}
	

	/**
	 * check if a student has a task
	 */
	public boolean exists(Long taskid, User user) {
		 Session session = sessionFactory.getCurrentSession();

		 try{

			 Criteria criteria = session.createCriteria(Task.class);
			 criteria.add(Restrictions.eq("taskId", taskid));			 
			 criteria.add(Restrictions.eq("user", user));

			 return criteria.list().size() > 0;
		 }catch(Exception e){
			 e.printStackTrace();
		 }
		 return false;
	}

	/**
	 *Retrieve a task according to the id  
	 */
	public Task getTaskById(Long taskid) {
		 try{
			 Session session = sessionFactory.getCurrentSession();
			 Criteria criteria = session.createCriteria(Task.class);
			 criteria.add(Restrictions.eq("taskId", taskid));			 
			 return (Task) criteria.uniqueResult();
		 }catch(Exception e){
			 e.printStackTrace();
		 }
		 return null;
	}
	
	public List<Test> getTestByTask(Long taskid){
		try{
			Session session = sessionFactory.getCurrentSession();
			return session.createQuery("FROM Test WHERE task_id = ?").setLong(0, taskid).list();

		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

        
	/**
	 * Read XML containing arguments presets.
         * @param path Servlet Context path
	 */
    public List<String[]> getPresetArguments(String path) {
        List<String[]> args = new java.util.ArrayList<String[]>();
        try {

            java.io.File fXmlFile = new java.io.File(path + "/WEB-INF/conf/compilerPresets.xml");

            //DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            //DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = dBuilder.parse(fXmlFile);

            doc.getDocumentElement().normalize();
            NodeList nList = doc.getElementsByTagName("argument");

            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) nNode;
                    String[] st = new String[3];

                    st[0] = eElement.getAttribute("langId");
                    st[1] = eElement.getElementsByTagName("description").item(0).getTextContent();
                    st[2] = eElement.getElementsByTagName("code").item(0).getTextContent();
                    /*
                     System.out.println("Argument id : " + eElement.getAttribute("id"));
                     System.out.println("Lang : " + eElement.getAttribute("langId="));
                     System.out.println("Description : " + eElement.getElementsByTagName("description").item(0).getTextContent());
                     System.out.println("Code : " + eElement.getElementsByTagName("code").item(0).getTextContent());
                     */
                    args.add(st);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return args;
    }
}
