/*
 * Copyright (C) 2021 favdb
 *
 * 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.ui.dialog;

import i18n.I18N;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JOptionPane;
import org.hibernate.Session;
import storybook.exim.importer.ImportDocument;
import storybook.model.EntityUtil;
import storybook.model.Model;
import storybook.model.book.Book;
import storybook.model.hbn.dao.ItemDAO;
import storybook.model.hbn.dao.LocationDAO;
import storybook.model.hbn.dao.PersonDAO;
import storybook.model.hbn.dao.SceneDAO;
import storybook.model.hbn.entity.AbstractEntity;
import storybook.model.hbn.entity.Item;
import storybook.model.hbn.entity.Location;
import storybook.model.hbn.entity.Person;
import storybook.model.hbn.entity.Scene;
import storybook.tools.html.Html;
import storybook.ui.MainFrame;
import storybook.ui.SbView;

/**
 *
 * @author favdb
 */
public class ScenesLinks {

	private static final String TT = "ScenesLinks", LINKS = "links.";

	public static boolean show(MainFrame mainFrame, Book.TYPE type) {
		if (EntityUtil.findEntities(mainFrame, type).isEmpty()) {
			JOptionPane.showMessageDialog(mainFrame,
			   I18N.getMsg(LINKS + type.toString().toLowerCase() + ".empty"),
			   I18N.getMsg(LINKS + type.toString().toLowerCase()),
			   JOptionPane.YES_OPTION);
			//LOG.trace("empty list for " + type.toString());
			return false;
		}
		ScenesLinks dlg = new ScenesLinks(mainFrame, type);
		if (!dlg.init()) {
			return false;
		}
		return dlg.exec();
	}

	private final MainFrame mainFrame;
	private boolean xternal;
	private final Book.TYPE type;

	public ScenesLinks(MainFrame mainFrame, Book.TYPE type) {
		this.mainFrame = mainFrame;
		this.type = type;
	}

	@SuppressWarnings("unchecked")
	private boolean init() {
		//LOG.trace(TT + ".init()");
		List list = EntityUtil.findEntities(mainFrame, Book.TYPE.PERSON);
		if (list.isEmpty()) {
			JOptionPane.showMessageDialog(mainFrame,
			   I18N.getMsg(LINKS + type.toString().toLowerCase() + ".empty"),
			   I18N.getMsg(LINKS + type.toString().toLowerCase()),
			   JOptionPane.YES_OPTION);
			//LOG.trace("init: empty list for " + type.toString());
			return false;
		}
		return JOptionPane.showConfirmDialog(mainFrame,
		   I18N.getMsg(LINKS + type.toString().toLowerCase() + ".info"),
		   I18N.getMsg(LINKS + type.toString().toLowerCase()),
		   JOptionPane.YES_NO_OPTION) == JOptionPane.YES_NO_OPTION;
	}

	@SuppressWarnings("unchecked")
	private boolean exec() {
		//LOG.trace(TT + ".exec()");
		xternal = mainFrame.getBook().isUseXeditor();
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		SceneDAO dao = new SceneDAO(session);
		List<Scene> scenes = dao.findAll();
		List entities;
		switch (type) {
			case PERSON:
				PersonDAO daoPerson = new PersonDAO(session);
				entities = daoPerson.findAll();
				break;
			case LOCATION:
				LocationDAO daoLocation = new LocationDAO(session);
				entities = daoLocation.findAll();
				break;
			case ITEM:
				ItemDAO daoItem = new ItemDAO(session);
				entities = daoItem.findAll();
				break;
			default:
				return false;
		}
		for (Scene scene : scenes) {
			update(session, scene, entities);
		}
		model.commit();
		mainFrame.getBookModel().fireAgain(mainFrame.getView(SbView.VIEWNAME.SCENES));
		mainFrame.getBookModel().fireAgain(mainFrame.getView(SbView.VIEWNAME.MEMORIA));
		mainFrame.getBookModel().fireAgain(mainFrame.getView(SbView.VIEWNAME.INFO));
		mainFrame.getBookModel().fireAgain(mainFrame.getView(SbView.VIEWNAME.READING));
		mainFrame.getBookModel().fireAgain(mainFrame.getView(SbView.VIEWNAME.MANAGE));
		mainFrame.getBookModel().fireAgain(mainFrame.getView(SbView.VIEWNAME.BOOK));
		return true;
	}

	private void update(Session session, Scene scene, List<AbstractEntity> entities) {
		//LOG.trace(TT + ".update(session, scene)");
		switch (type) {
			case ITEM:
				updateItems(session, scene, entities);
				break;
			case LOCATION:
				updateLocations(session, scene, entities);
				break;
			case PERSON:
				updatePersons(session, scene, entities);
				break;
			default:
				break;
		}
	}

	private void updateItems(Session session, Scene scene, List<AbstractEntity> entities) {
		//LOG.trace(TT + ".updateItems(session, scene)");
		String text = Html.htmlToText(scene.getSummary());
		if (xternal && !scene.getOdf().isEmpty()) {
			ImportDocument doc = new ImportDocument(mainFrame, new File(scene.getOdf()));
			if (doc.openDocument()) {
				text = doc.getContentAsTxt();
				doc.close();
			}
		}
		List<Item> lp = new ArrayList<>();
		for (Object p : entities) {
			if (text.contains(((Item) p).getName())) {
				lp.add((Item) p);
			}
		}
		scene.setItems(lp);
		session.saveOrUpdate(scene);
	}

	private void updateLocations(Session session, Scene scene, List<AbstractEntity> entities) {
		//LOG.trace(TT + ".updateLocations(session, scene=" + scene.getName() + ") initial size=" + scene.getLocations().size());
		String text = Html.htmlToText(scene.getSummary());
		if (xternal && !scene.getOdf().isEmpty()) {
			ImportDocument doc = new ImportDocument(mainFrame, new File(scene.getOdf()));
			if (doc.openDocument()) {
				text = doc.getContentAsTxt();
				doc.close();
			}
		}
		List<Location> lp = new ArrayList<>();
		if (entities != null) {
			for (Object p : entities) {
				if (text.contains(((Location) p).getName()) && !lp.contains(p)) {
					lp.add((Location) p);
				}
			}
		}
		scene.setLocations(lp);
		session.saveOrUpdate(scene);
	}

	private void updatePersons(Session session, Scene scene, List<AbstractEntity> entities) {
		//LOG.trace(TT + ".updatePersons(session, scene)");
		String text = Html.htmlToText(scene.getSummary());
		if (xternal && !scene.getOdf().isEmpty()) {
			ImportDocument doc = new ImportDocument(mainFrame, new File(scene.getOdf()));
			if (doc.openDocument()) {
				text = doc.getContentAsTxt();
				doc.close();
			}
		}
		text = text.replaceAll("\\p{Punct}", " ").replace("  ", " ");
		List<String> tl = new ArrayList<>(Arrays.asList(text.split(" ")));
		List<Person> lp = new ArrayList<>();
		for (Object p : entities) {
			String abbr = ((Person) p).getAbbr();
			if (tl.contains(abbr) || tl.contains("[" + abbr + "]")) {
				lp.add((Person) p);
			} else {
				String firstlast = ((Person) p).getFirstname() + " " + ((Person) p).getLastname();
				String lastfirst = ((Person) p).getLastname() + " " + ((Person) p).getFirstname();
				if (text.contains(firstlast) || text.contains(lastfirst)) {
					lp.add((Person) p);
				}
			}
		}
		scene.setPersons(lp);
		session.saveOrUpdate(scene);
	}

}
