/*
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.entity;

import i18n.I18N;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.swing.Icon;
import resources.icons.ICONS;
import resources.icons.IconUtil;
import storybook.model.DB.DATA;
import storybook.model.book.Book;
import storybook.model.hbn.dao.DAOutil;
import storybook.tools.Period;
import storybook.tools.xml.XmlUtil;

public abstract class AbstractTaglink extends AbstractEntity {

	public static final int TYPE_TAG = 0;
	public static final int TYPE_ITEM = 1;

	protected Integer type = TYPE_ITEM;
	private Scene startScene;
	private Scene endScene;
	private Person person;
	private Location location;

	public AbstractTaglink() {
		super(Book.TYPE.TAGLINK, "000");
	}

	public AbstractTaglink(Book.TYPE objtype, String common) {
		super(objtype, common);
	}

	public AbstractTaglink(Book.TYPE objtype, String common, ResultSet rs) {
		super(objtype, common, rs);
		try {
			type = rs.getInt("type");
			startScene = rs.getObject("startScene", Scene.class);
			endScene = rs.getObject("endScene", Scene.class);
			person = rs.getObject("person", Person.class);
			location = rs.getObject("location", Location.class);
		} catch (SQLException ex) {
			//empty
		}
	}

	@Override
	public String getName() {
		if (super.getName().isEmpty()) {
			setName(this.getDescription());
		}
		return super.getName();
	}

	public Integer getType() {
		return this.type;
	}

	public void setType(Integer type) {
		this.type = type;
	}

	public Scene getStartScene() {
		return this.startScene;
	}

	public boolean hasStartScene() {
		return startScene != null;
	}

	public void setStartScene(Scene sceneStart) {
		this.startScene = sceneStart;
	}

	public Scene getEndScene() {
		return this.endScene;
	}

	public boolean hasEndScene() {
		return endScene != null;
	}

	public void setEndScene(Scene sceneEnd) {
		this.endScene = sceneEnd;
	}

	public Person getPerson() {
		return this.person;
	}

	public boolean hasPerson() {
		return person != null;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public void setPerson() {
		this.person = null;
	}

	public Location getLocation() {
		return this.location;
	}

	public boolean hasLocation() {
		return location != null;
	}

	public void setLocation() {
		this.location = null;
	}

	public void setLocation(Location location) {
		this.location = location;
	}

	public boolean hasOnlyScene() {
		return startScene != null && endScene == null && person == null && location == null;
	}

	public boolean hasPeriod() {
		return (this.getStartScene() != null && this.getEndScene() != null);
	}

	public Period getPeriod() {
		if (hasPeriod()) {
			return new Period(getStartScene().getScenets(), getEndScene().getScenets());
		}
		if (hasStartScene()) {
			return new Period(getStartScene().getScenets(), getStartScene().getScenets());
		}
		return null;
	}

	public boolean hasLocationOrPerson() {
		return hasLocation() || hasPerson();
	}

	@Override
	public Icon getIcon() {
		if (type == null || type == TYPE_ITEM) {
			return (IconUtil.getIconSmall(ICONS.K.ENT_ITEMLINK));
		} else {
			return (IconUtil.getIconSmall(ICONS.K.ENT_TAGLINK));
		}
	}

	@Override
	public String toString() {
		StringBuilder buf = new StringBuilder();
		if (hasPerson()) {
			buf.append(person.toString());
		}
		if (hasLocation()) {
			if (buf.length() > 0) {
				buf.append(", ");
			}
			buf.append(location.toString());
		}
		if (hasOnlyScene()) {
			buf.append(" ");
			buf.append(I18N.getMsg("scene"));
			buf.append(" ");
			buf.append(startScene.getChapterSceneNo(false));
		} else {
			if (hasStartScene()) {
				if (buf.length() > 0) {
					buf.append(",");
				}
				buf.append(" ");
				buf.append(I18N.getMsg("scene"));
				buf.append(" ");
				buf.append(startScene.getChapterSceneNo(false));
			}
			if (hasPeriod()) {
				buf.append(" - ");
			}
			if (hasEndScene()) {
				buf.append(endScene.getChapterSceneNo(false));
			}
			if (hasPeriod()) {
				buf.append(" (");
				buf.append(getPeriod().getShortString());
				buf.append(")");
			}
		}
		return buf.toString() + (hasNotes() ? "*" : "");
	}

	@Override
	public String toCsv(String quoteStart, String quoteEnd, String separator) {
		StringBuilder b = new StringBuilder();
		b.append(quoteStart).append(getId().toString()).append(quoteEnd).append(separator);
		b.append(quoteStart).append(getClean(getStartScene())).append(quoteEnd).append(separator);
		b.append(quoteStart).append(getClean(getEndScene())).append(quoteEnd).append(separator);
		b.append(quoteStart).append(getClean(getLocation())).append(quoteEnd).append(separator);
		b.append(quoteStart).append(getClean(getPerson())).append(quoteEnd).append("\n");
		return (b.toString());
	}

	@Override
	public String toHtml() {
		return (toCsv("<td>", "</td>", "\n"));
	}

	@Override
	public String toText() {
		return (toCsv("", "", "\t"));
	}

	@Override
	public String toDetail(Integer detailed) {
		StringBuilder b = new StringBuilder();
		b.append(getInfo(detailed, DATA.SCENE_START, getStartScene()));
		b.append(getInfo(detailed, DATA.SCENE_END, getEndScene()));
		b.append(getInfo(detailed, DATA.PERSONS, person));
		b.append(getInfo(detailed, DATA.LOCATIONS, location));
		return b.toString();
	}

	@Override
	public String toXml() {
		StringBuilder b = new StringBuilder();
		String typestr = "taglink";
		switch (getType()) {
			case 0:
				typestr = "taglink";
				break;
			case 1:
				typestr = "itemlink";
				break;
		}
		b.append("<").append(typestr).append(" \n");
		b.append(xmlCommon());
		if (getStartScene() != null) {
			b.append(XmlUtil.setAttribute("startScene", getClean(getStartScene().getTitle())));
		}
		if (getEndScene() != null) {
			b.append(XmlUtil.setAttribute("endScene", getClean(getEndScene().getTitle())));
		}
		if (getLocation() != null) {
			b.append(XmlUtil.setAttribute(DAOutil.LOCATION, getClean(getLocation().getId())));
		}
		if (getPerson() != null) {
			b.append(XmlUtil.setAttribute(DAOutil.PERSON, getClean(getPerson().getId())));
		}
		b.append("/>\n");
		return (b.toString());
	}

	@Override
	@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
	public boolean equals(Object obj
	) {
		if (!super.equals(obj)) {
			return false;
		}
		AbstractTaglink test = (AbstractTaglink) obj;
		if (!Objects.equals(type, test.getType())) {
			return false;
		}
		boolean ret = true;
		ret = ret
		   && equalsLongNullValue(startScene == null ? null
			  : startScene.getId(), test.getStartScene() == null ? null
			  : test.getStartScene().getId());
		ret = ret
		   && equalsLongNullValue(endScene == null ? null : endScene.getId(),
			  test.getEndScene() == null ? null : test.getEndScene().getId());
		ret = ret
		   && equalsLongNullValue(person == null ? null : person.getId(),
			  test.getPerson() == null ? null : test.getPerson().getId());
		ret = ret
		   && equalsLongNullValue(location == null ? null : location.getId(),
			  test.getLocation() == null ? null : test.getLocation().getId());
		return ret;
	}

	@Override
	public int hashCode() {
		int hash = super.hashCode();
		hash = hash * 31 + (type != null ? type.hashCode() : 0);
		hash = hash * 31 + (startScene != null ? startScene.hashCode() : 0);
		hash = hash * 31 + (endScene != null ? endScene.hashCode() : 0);
		hash = hash * 31 + (person != null ? person.hashCode() : 0);
		hash = hash * 31 + (location != null ? location.hashCode() : 0);
		return hash;
	}

	public static List<String> getTable() {
		List<String> ls = new ArrayList<>();
		String tableName = "tag_link";
		AbstractEntity.getTable(tableName, ls);
		ls.add(tableName + ",type,Integer,0");
		ls.add(tableName + ",start_scene_id,Integer,0");
		ls.add(tableName + ",end_scene_id,Integer,0");
		ls.add(tableName + ",character_id,Integer,0");
		ls.add(tableName + ",location_id,Integer,0");
		ls.add(tableName + ",item_id,Integer,0");
		ls.add(tableName + ",tag_id,Integer,0");
		return (ls);
	}

}
