package org.yacos.web.PCmember.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.ModelAndViewDefiningException;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.yacos.core.article.Article;
import org.yacos.core.article.IArticleManager;
import org.yacos.core.article.Article.State;
import org.yacos.core.conferences.Conference;
import org.yacos.core.conferences.IConferenceManager;
import org.yacos.core.evaluation.Criterion;
import org.yacos.core.evaluation.IEvaluationManager;
import org.yacos.core.evaluation.Rating;
import org.yacos.core.evaluation.Report;
import org.yacos.core.users.IUserManager;
import org.yacos.core.users.User;
import org.yacos.web.PCmember.form.FormEvaluation;
import org.yacos.web.PCmember.form.SimpleCriterion;
import org.yacos.web.system.session.SessionService;

public class EvaluationController  extends SimpleFormController {

	/** Logger for this class and subclasses */
	protected final Log logger = LogFactory.getLog(getClass());

	private IArticleManager articleManager;
	private IUserManager userManager;
	private IConferenceManager conferenceManager;
	private IEvaluationManager evaluationManager;

	public IArticleManager getArticleManager() {
		return articleManager;
	}

	public void setArticleManager(IArticleManager articleManager) {
		this.articleManager = articleManager;
	}

	public IUserManager getUserManager() {
		return userManager;
	}

	public void setUserManager(IUserManager userManager) {
		this.userManager = userManager;
	}

	public IConferenceManager getConferenceManager() {
		return conferenceManager;
	}

	public void setConferenceManager(IConferenceManager conferenceManager) {
		this.conferenceManager = conferenceManager;
	}

	public IEvaluationManager getEvaluationManager() {
		return evaluationManager;
	}

	public void setEvaluationManager(IEvaluationManager evaluationManager) {
		this.evaluationManager = evaluationManager;
	}


	@Override
	protected Object formBackingObject(HttpServletRequest request)
	throws Exception {

		
		Conference conf = SessionService.getInstance().getCurrentConference();
		String memberId = SessionService.getInstance().getCurrentUserLogin();
		
		
		List<Criterion> criterionList =	evaluationManager.getCriterions(conf.getId());
		String articleId = request.getParameter("id");
		String action = request.getParameter("action");
		boolean haveArticle = false;
		List<Article> listarticles = articleManager.getArticlesOfMember(conf.getId(), memberId);
		for (Article article : listarticles) {
			if(article.getId() == Integer.parseInt(articleId)){
				haveArticle = true;
			}
		}
		
		listarticles = articleManager.getArticlesOfReferee(memberId);
		for (Article article : listarticles) {
			if(article.getId() == Integer.parseInt(articleId)){
				haveArticle = true;
			}
		}
		
		if(!haveArticle){
			throw new ModelAndViewDefiningException(new ModelAndView("denied"));
		}
		// TODO : verifier que le gars a le droit d'evaluer cette article
		// TODO : s'il existe deja une al, mais que l'action est pas modify, virer le gars

		if (action == null || action.equals("")) {
			Report report = evaluationManager.getReportforArticleAndReferee(Integer.parseInt(articleId), memberId);
			if(report != null){
				throw new ModelAndViewDefiningException(new ModelAndView("denied"));
			}
			try {
				Integer id = new Integer(articleId);
				Article a = articleManager.getArticle(id);

				if (a == null)
					throw new ModelAndViewDefiningException(new ModelAndView("404error"));

				String title = a.getTitle();

				FormEvaluation fe = new FormEvaluation();

				List<SimpleCriterion> liste = new ArrayList<SimpleCriterion>();
				for (Criterion c : criterionList) {  
					SimpleCriterion sc = new SimpleCriterion(c.getName(), c.getMin_rating(), c.getMax_rating(), c.getMin_rating(), c.getId());
					liste.add(sc);
				}

				fe.setSimpleRatings(liste);
				fe.setTitle(title);

				return fe;
			}
			catch (NumberFormatException e) {
				throw new ModelAndViewDefiningException(new ModelAndView("404error"));
			}
		}
		else if (action.equals("modify")) {

			try {
				Integer id = new Integer(articleId);
				Article a = articleManager.getArticle(id);

				if (a == null)
					throw new ModelAndViewDefiningException(new ModelAndView("404error"));

				String title = a.getTitle();

				Report rpt = evaluationManager.getReportforArticleAndReferee(a.getId(), SessionService.getInstance().getCurrentUserLogin());
				if (rpt == null)
					throw new ModelAndViewDefiningException(new ModelAndView("404error"));

				List<Rating> ratings = evaluationManager.getRatingForReport(rpt.getId());

				FormEvaluation fe = new FormEvaluation();

				List<SimpleCriterion> liste = new ArrayList<SimpleCriterion>();
				for (Rating r : ratings) {  
					SimpleCriterion sc = new SimpleCriterion(r.getCriterion().getName(), r.getCriterion().getMin_rating(), r.getCriterion().getMax_rating(), r.getValue(), r.getCriterion().getId());
					liste.add(sc);
				}

				fe.setSimpleRatings(liste);
				fe.setCommentAuthor(rpt.getCommentAuthor());
				fe.setCommentPCMember(rpt.getCommentPCMember());
				fe.setTitle(title);

				return fe;
			}
			catch (NumberFormatException e) {
				throw new ModelAndViewDefiningException(new ModelAndView("404error"));
			}
		}
		else {
			throw new ModelAndViewDefiningException(new ModelAndView("404error"));
		}
	}

	@Override
	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
	throws Exception {

		String articleId = request.getParameter("id");
		String action = request.getParameter("action");

		logger.info("Article id: " + articleId);

		if (action == null || action.equals("")) {

			try {

				FormEvaluation fe = (FormEvaluation)command;

				List<SimpleCriterion> liste = fe.getSimpleRatings();
				String commentAuthor = fe.getCommentAuthor();
				String commentPCMember = fe.getCommentPCMember();
				List<Rating> listeRating = new ArrayList<Rating>(); 

				for(SimpleCriterion sc : liste){
					Rating rt = new Rating();
					Criterion cn = new Criterion();

					cn.setMax_rating(sc.getMax_rating());
					cn.setMin_rating(sc.getMin_rating());
					cn.setName(sc.getName());
					cn.setId(sc.getId());
                   
					rt.setCriterion(cn);
					rt.setValue(sc.getValue());
					listeRating.add(rt);
				}

				Integer id = new Integer(articleId);

				Article article = articleManager.getArticle(id);

				if (article == null)
					throw new ModelAndViewDefiningException(new ModelAndView("404error"));

				User current = SessionService.getInstance().getCurrentUser();

				Report rpt = evaluationManager.addReport(id, commentPCMember, commentAuthor, listeRating, current.getLogin());

				for (Rating rt : listeRating) {
					evaluationManager.addRating(rt.getValue(), rt.getCriterion().getId(), rpt.getId());
				}

				article.setState(State.EVALUATED);
				articleManager.updateArticle(article);
				
				Map<String, Object> model = new HashMap<String, Object>();
				model.put("report", rpt);
				
				String addrFrom = request.getHeader("REFERER");
				addrFrom = addrFrom + "&action=modify";
				
				model.put("whereIcome", addrFrom);

				return new ModelAndView("createReport", model);

			}
			catch (NumberFormatException e) {
				throw new ModelAndViewDefiningException(new ModelAndView("404error"));
			}
		}
		else if (action.equals("modify")) {
			try {

				Integer id = new Integer(articleId);

				Article article = articleManager.getArticle(id);

				if (article == null)
					throw new ModelAndViewDefiningException(new ModelAndView("404error"));

				User current = SessionService.getInstance().getCurrentUser();
				
				Report rpt = evaluationManager.getReportforArticleAndReferee(article.getId(), current.getLogin());
				if (rpt == null)
					throw new ModelAndViewDefiningException(new ModelAndView("404error"));

				List<Rating> ratings = evaluationManager.getRatingForReport(rpt.getId());
								
				FormEvaluation fe = (FormEvaluation)command;

				List<SimpleCriterion> liste = fe.getSimpleRatings();
				String commentAuthor = fe.getCommentAuthor();
				String commentPCMember = fe.getCommentPCMember();
 
				
				for(SimpleCriterion sc : liste) {
					Rating rt = new Rating();
					for (Rating r : ratings) {
						if (r.getCriterion().getId().intValue() == sc.getId().intValue()) {
							rt = r;
						}
					}
					
					Criterion cn = rt.getCriterion();

					cn.setMax_rating(sc.getMax_rating());
					cn.setMin_rating(sc.getMin_rating());
					cn.setName(sc.getName());
					cn.setId(sc.getId());

					rt.setCriterion(cn);
					rt.setValue(sc.getValue());
				}				
			
				rpt.setCommentAuthor(commentAuthor);
				rpt.setCommentPCMember(commentPCMember);
				rpt.setRatings(ratings);
				
				evaluationManager.updateReport(rpt);

				for (Rating rt : ratings) {
					evaluationManager.updateRating(rt);
				}
				
				Map<String, Object> model = new HashMap<String, Object>();
				model.put("report", rpt);
				
				String addrFrom = request.getHeader("REFERER");				
				model.put("whereIcome", addrFrom);

				return new ModelAndView("createReport", model);

			}
			catch (NumberFormatException e) {
				throw new ModelAndViewDefiningException(new ModelAndView("404error"));
			}
		}
		else {
			throw new ModelAndViewDefiningException(new ModelAndView("404error"));
		}
	}
}