/*
Storybook: Open Source software for novelists and authors.
Copyright (C) 2008 - 2012 Martin Mustun

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package storybook.model.hbn.dao;

import com.googlecode.genericdao.dao.hibernate.GenericDAO;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.persistence.NonUniqueResultException;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import storybook.model.hbn.entity.AbstractEntity;
import storybook.model.hbn.entity.Chapter;
import storybook.model.hbn.entity.Endnote;
import storybook.model.hbn.entity.Scene;
import storybook.tools.LOG;
import storybook.ui.dialog.ExceptionDlg;

public class EndnoteDAO extends _GenericDAO<Endnote, Long>
		implements EndnoteDAOInterface {

	public EndnoteDAO() {
		super();
	}

	public EndnoteDAO(Session session) {
		super(session);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Endnote> findAll() {
		Query query = session.createQuery("from Endnote as s"
				+ " order by number");
		return (List<Endnote>) query.list();
	}

	@SuppressWarnings("unchecked")
	public List<Endnote> findAllBySort(Integer type) {
		StringBuilder buf = new StringBuilder("from Endnote as s");
		buf.append(" where s.type=").append(type.toString());
		buf.append(" order by sort");
		Query query = session.createQuery(buf.toString());
		return (List<Endnote>) query.list();
	}

	@SuppressWarnings("unchecked")
	public List<Endnote> findAllByScene(Integer type) {
		StringBuilder buf = new StringBuilder("from Endnote as s");
		buf.append(" where s.type=").append(type.toString());
		buf.append(" order by scene, sort");
		Query query = session.createQuery(buf.toString());
		return (List<Endnote>) query.list();
	}

	@SuppressWarnings("unchecked")
	public List<Endnote> findAll(Integer type, Scene scene) {
		StringBuilder buf = new StringBuilder("from Endnote as en");
		buf.append(" where en.type=").append(type.toString());
		buf.append(" order by sort");
		Query query = session.createQuery(buf.toString());
		List<Endnote> list = (List<Endnote>) query.list();
		List<Endnote> endnotes = new ArrayList<>();
		for (Endnote en : list) {
			if (en.getScene() != null && en.getScene().equals(scene)) {
				endnotes.add(en);
			}
		}
		return endnotes;
	}

	@SuppressWarnings("unchecked")
	public List<Endnote> findAll(Scene scene) {
		StringBuilder buf = new StringBuilder("select Endnote from Endnote as s");
		if (scene != null) {
			buf.append(" where s.scene=:scene");
		}
		buf.append(" order by number");
		Query query = session.createQuery(buf.toString());
		if (scene != null) {
			query.setEntity(DAOutil.SCENE, scene);
		}
		return (List<Endnote>) query.list();
	}

	@SuppressWarnings("unchecked")
	public List<Scene> findScenes(Integer type) {
		List<Scene> scenes = new ArrayList<>();
		for (Endnote en : findAll()) {
			if (Objects.equals(type, en.getType())) {
				if (!scenes.contains(en.getScene())) {
					scenes.add(en.getScene());
				}
			}
		}
		return scenes;
	}

	public int getNextNumber() {
		return getMaxNumber() + 1;
	}

	public int getMaxNumber() {
		Query query = session.createQuery("select max(number) from Endnote");
		if (query.uniqueResult() == null) {
			return 0;
		}
		return (Integer) query.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public boolean checkIfNumberExists(AbstractEntity entity) {
		try {
			Endnote newEndnote = (Endnote) entity;
			Integer newNumber = newEndnote.getNumber();
			if (!entity.isTransient()) {
				EndnoteDAO dao = new EndnoteDAO(session);
				Endnote oldEndnote = dao.find(entity.getId());
				Integer oldNumber = oldEndnote.getNumber();
				Criteria crit = session.createCriteria(Chapter.class);
				crit.add(Restrictions.eq(DAOutil.NUMBER, newNumber));
				List<Endnote> entities = (List<Endnote>) crit.list();
				List<Integer> numbers = new ArrayList<>();
				for (Endnote e : entities) {
					numbers.add(e.getNumber());
				}
				if (newNumber.equals(oldNumber)) {
					numbers.remove(newNumber);
				}
				return numbers.isEmpty();
			}
			Criteria crit = session.createCriteria(Endnote.class);
			crit.add(Restrictions.eq(DAOutil.NUMBER, newNumber));
			List<Endnote> entities = (List<Endnote>) crit.list();
			return entities.size() <= 0;
		} catch (NonUniqueResultException e) {
			ExceptionDlg.show(this.getClass().getSimpleName()
					+ ".checkIfNumberExists(entity=" + LOG.trace(entity)
					+ ") NonUniqueResultException", e);
			return true;
		}
	}

}

interface EndnoteDAOInterface extends GenericDAO<Endnote, Long> {
}
