package dendrarium.portal.answer;

import dendrarium.core.entities.Answer;
import dendrarium.core.entities.User;
import dendrarium.portal.PaginatedList;
import dendrarium.trees.AnswerType;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions.*;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.log.Log;

/**
 * Bean dostarczajacy list odpowiedzi zalogowanego uzytkownika
 *
 * @author Piotr Achinger <piotr.achinger at gmail.com>
 */
@Name("answerList")
@Scope(ScopeType.SESSION)
public class AnswerList implements Serializable {

    private static final int PAGE_SIZE = 10;

    @In
    Session session;

    @DataModel
    private List<Answer> answersToConfirm;

    private PaginatedList<Answer> answersToConfirmPL;

    @DataModel
    private List<Answer> answersInProgress;

    private PaginatedList<Answer> answersInProgressPL;

    @DataModel
    private List<Answer> myAnswers;

    private PaginatedList<Answer> myAnswersPL;

    @DataModel
    private List<Answer> interventions;

    private PaginatedList<Answer> interventionsPL;

    @RequestParameter
    public Integer page_no;

    @RequestParameter
    public String list_id;

    @In
    private User user;

    @Logger
    Log log;

    Integer tab;

    private List<AnswerType> answerTypeFilters;

    private AnswerType answerTypeFilter;

    private String textFilter = "";

    public AnswerList() {
        answerTypeFilters = Arrays.asList(AnswerType.values());
        answerTypeFilter = null;
    }

    private String makeQueryText(String list_id) {
        String query = "";
        if ("answersToConfirm".equals(list_id)) {
            query = "from Answer a where a.user=:user and a.taskBusinessProcess.current = TRUE and "
                    + "a.taskBusinessProcess.state = dendrarium.core.entities.TaskBusinessProcessState.COLLISION and "
                    + "a.confirmed = false ";
        } else if ("myAnswers".equals(list_id)) {
            query = "from Answer a where a.user=:user and "
                    + "(a.taskBusinessProcess.superAnswer = null or a.taskBusinessProcess.superAnswer != a) and "
                    + "(a.accepted = true or a.taskBusinessProcess.superAnswer != null) and "
                    + "a.taskBusinessProcess.current = TRUE and "
                    + "(a.taskBusinessProcess.state != dendrarium.core.entities.TaskBusinessProcessState.COLLISION or "
                    + "a.confirmed = true) ";
        } else if ("answersInProgress".equals(list_id)) {
            query = "from Answer a where a.user=:user and a.accepted = false and a.taskBusinessProcess.current = TRUE and "
                    + "a.taskBusinessProcess.superAnswer = null ";
        } else if ("interventions".equals(list_id)) {
            query = "from Answer a where a.user=:user and a.taskBusinessProcess.current = TRUE and "
                    + "a.taskBusinessProcess.state = dendrarium.core.entities.TaskBusinessProcessState.COLLISION_SOLVED";
        }

        //teraz filtry
        if (isActiveTab(list_id)) {
            if (answerTypeFilter != null) {
                query += " and a.type = :type";
            }

            if (!textFilter.equals("")) {
                query += " and a.taskBusinessProcess.task.sentence like :text";
            }
        }

        return query;
    }

    private void applyFilters(Query q) {
        if (answerTypeFilter != null) {
            q.setParameter("type", answerTypeFilter);
        }
        if (!textFilter.equals("")) {
            q.setParameter("text", "%" + textFilter + "%");
        }
    }

    private boolean isActiveTab(String list_id) {
        return tab == null || ("answersToConfirm".equals(list_id) && tab == 0)
                || ("answersInProgress".equals(list_id) && tab == 1)
                || ("myAnswers".equals(list_id) && tab == 2)
                || ("interventions".equals(list_id) && tab == 3);
    }

    private Long listCount(String list_id) {
        Query q = session.createQuery("select count(a) " + makeQueryText(list_id));
        if (isActiveTab(list_id)) {
            applyFilters(q);
        }
        return (Long) q.setParameter("user", user).uniqueResult();
    }

    private Query makeQuery(String list_id) {
        String order;
        if ("interventions".equals(list_id))
            order = " order by a.taskBusinessProcess.superAnswer.selectDate desc";
        else
            order = " order by a.taskBusinessProcess.packet.id, a.taskBusinessProcess.index";
        Query q = session.createQuery(makeQueryText(list_id) + order);
        if (isActiveTab(list_id)) {
            applyFilters(q);
        }
        return q.setParameter("user", user);
    }

    //@Factory("answersToConfirm")
    //@Observer("tbpchangestate")
    public void getAnswersToConfirm() {
        Query allAnswersToConfirm = makeQuery("answersToConfirm");
        Integer page = 0;

        if (answersToConfirmPL != null) {
            page = answersToConfirmPL.getPageNo();
        }
        answersToConfirmPL = new PaginatedList<Answer>(listCount("answersToConfirm"), allAnswersToConfirm, PAGE_SIZE);
        getPage(page, "answersToConfirm");
        //return answersToConfirm;
    }

    //@Factory("answersInProgress")
    //@Observer("tbpchangestate")
    public void getAnswersInProgress() {
        Query allAnswersInProgress = makeQuery("answersInProgress");
        Integer page = 0;

        if (answersInProgressPL != null) {
            page = answersInProgressPL.getPageNo();
        }
        answersInProgressPL = new PaginatedList<Answer>(listCount("answersInProgress"), allAnswersInProgress, PAGE_SIZE);
        getPage(page, "answersInProgress");
        //return answersInProgress;
    }

    //@Factory("myAnswers")
    //@Observer("tbpchangestate")
    public void getMyAnswers() {
        Query allMyAnswers = makeQuery("myAnswers");
        Integer page = 0;

        if (myAnswersPL != null) {
            page = myAnswersPL.getPageNo();
        }
        myAnswersPL = new PaginatedList<Answer>(listCount("myAnswers"), allMyAnswers, PAGE_SIZE);
        getPage(page, "myAnswers");
        //return myAnswers;
    }

    public void getInterventions() {
        Query q = makeQuery("interventions");
        Integer page = 0;

        if (interventionsPL != null) {
            page = interventionsPL.getPageNo();
        }
        interventionsPL = new PaginatedList<Answer>(listCount("interventions"), q, PAGE_SIZE);
        getPage(page, "interventions");
    }

    private void getPage(int page, String list_id) {
        Query q = makeQuery(list_id);
        if ("answersInProgress".equals(list_id)) {
            answersInProgressPL.getPage(q, page);
            answersInProgress = answersInProgressPL.getCurrentPage();
        }
        if ("myAnswers".equals(list_id)) {
            myAnswersPL.getPage(q, page);
            myAnswers = myAnswersPL.getCurrentPage();
        }
        if ("answersToConfirm".equals(list_id)) {
            answersToConfirmPL.getPage(q, page);
            answersToConfirm = answersToConfirmPL.getCurrentPage();
        }
        if ("interventions".equals(list_id)) {
            interventionsPL.getPage(q, page);
            interventions = interventionsPL.getCurrentPage();
        }
    }

    public void getPage() {
        getPage(page_no, list_id);
    }

    public PaginatedList<Answer> getAnswersInProgressPL() {
        return answersInProgressPL;
    }

    public PaginatedList<Answer> getAnswersToConfirmPL() {
        return answersToConfirmPL;
    }

    public PaginatedList<Answer> getMyAnswersPL() {
        return myAnswersPL;
    }

    public PaginatedList<Answer> getInterventionsPL() {
        return interventionsPL;
    }

    public void setTab(int nr) {
        if (!textFilter.equals("") || answerTypeFilter != null) {
            answersToConfirmPL = null;
            answersInProgressPL = null;
            myAnswersPL = null;
            interventionsPL = null;
        }
        textFilter = "";
        answerTypeFilter = null;
        tab = nr;
    }

    public Boolean lists() {
        getAnswersToConfirm();
        getAnswersInProgress();
        getMyAnswers();
        getInterventions();
        return false;
    }

    public int getTab() {
        if (answersToConfirmPL == null) {
            lists();
        }
        if (tab == null) {
            lists();
            if (!answersToConfirmPL.isEmpty()) {
                tab = 0;
            } else if (!answersInProgressPL.isEmpty()) {
                tab = 1;
            } else if (!myAnswersPL.isEmpty()) {
                tab = 2;
            } else if (!interventionsPL.isEmpty()) {
                tab = 3;
            } else {
                tab = 0;
            }
        }
        return tab;
    }

    public AnswerType getAnswerTypeFilter() {
        return answerTypeFilter;
    }

    public void setAnswerTypeFilter(AnswerType answerTypeFilter) {
        this.answerTypeFilter = answerTypeFilter;
    }

    public List<AnswerType> getAnswerTypeFilters() {
        return answerTypeFilters;
    }

    public void setAnswerTypeFilters(List<AnswerType> answerTypeFilters) {
        this.answerTypeFilters = answerTypeFilters;
    }

    public String getTextFilter() {
        return textFilter;
    }

    public void setTextFilter(String textFilter) {
        this.textFilter = textFilter;
    }

    public void getSearchAnswers() {
        answersToConfirmPL = null;
        answersInProgressPL = null;
        myAnswersPL = null;
        interventionsPL = null;
    }
}
