/*
 * Copyright (C) 2016 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package storybook.exim.exporter;

import i18n.I18N;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import org.hibernate.Session;
import storybook.App;
import storybook.Pref;
import storybook.model.DB.DATA;
import storybook.model.Model;
import storybook.model.book.Book;
import storybook.model.book.BookParam;
import storybook.model.hbn.dao.*;
import storybook.model.hbn.entity.*;
import storybook.tools.LOG;
import storybook.ui.MainFrame;
import storybook.ui.SbView;

/**
 * class for exporting a table
 *
 * @author favdb
 */
public class ExportTable extends AbstractExport {
	//TODO à réécrire pour profiter pleinement de getColumns et getRow

	public BookParam bookParam;

	/**
	 * export a table
	 *
	 * @param mainFrame
	 * @param format
	 */
	public ExportTable(MainFrame mainFrame, String format) {
		super(mainFrame, format);
		this.bookParam = mainFrame.getBook().getParam();
	}

	public enum KW {
		ID,
		NAME,
		TITLE,
		BLURB,
		DESCRIPTION,
		FILE,
		NOTES,
		ASSISTANT,
		STATUS,
		CATEGORY,
		EXPORT,
		DATABASE,
		XML,
		HTML,
		KEY,
		VALUE,
		STEP,
		POLTI,
		INFO,
		PARAM,
		BACKUP,
		DIRECTORY,
		AUTO,
		INCREMENT,
		EDITOR,
		MODLESS,
		XUSE,
		EXTEND,
		TEMPLATE,
		IMPORT,
		LAYOUT,
		SCENE_START, SCENE_END,
		LOCATION,
		PERSON,
		ADRESS,
		CITY,
		COUNTRY,
		ALTITUDE,
		NUMBER,
		DATE,
		COLOR,
		SORT;

		@Override
		public String toString() {
			return this.name().toLowerCase().replace("_", ".");
		}
	}

	public static void exportTable(MainFrame m, SbView view) {
		exportTable(m, view, App.preferences.getString(Pref.KEY.EXP_FORMAT));
	}

	public static void exportTable(MainFrame m, SbView view, String format) {
		//App.trace("ExportTable.exportTable(mainFrame, view="+view.toString()+", f="+f+")");
		exportTable(m, view.getName(), format);
	}

	public static void exportTable(MainFrame m, String viewName, String format) {
		//App.trace("ExportTable.exportTable(mainFrame, v="+v+", f="+f+")");
		ExportTable export = new ExportTable(m, format);
		if (export.askFileExists(viewName)
		   && JOptionPane.showConfirmDialog(m,
			  I18N.getMsg("export.replace", export.param.getFileName()),
			  I18N.getMsg(KW.EXPORT.toString()),
			  JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
			return;
		}
		if (!export.openFile("table_" + viewName, false)) {
			return;
		}
		export.writeTable(viewName);
		export.closeFile(true);
	}

	public void setDir(String d) {
		param.setDirectory(d);
	}

	public void setFormat(String f) {
		param.setFormat(f);
	}

	public void writeTable(String name) {
		//App.trace("ExportTable.writeTable(name="+name+")");
		if (!isOpened) {
			return;
		}
		switch (Book.getTYPE(name)) {
			case ATTRIBUTE:
			case ATTRIBUTES:
				writeAttributes();
				break;
			case CATEGORY:
			case CATEGORIES:
				writeCategories();
				break;
			case CHAPTER:
			case CHAPTERS:
				writeChapters();
				break;
			case ENDNOTE:
			case ENDNOTES:
				writeEndnotes();
				break;
			case EVENT:
			case EVENTS:
				writeEvents();
				break;
			case GENDER:
			case GENDERS:
				writeGenders();
				break;
			case IDEA:
			case IDEAS:
				writeIdeas();
				break;
			case INTERNAL:
			case INTERNALS:
				writeInternal();
				break;
			case ITEM:
			case ITEMS:
				writeItems();
				break;
			case ITEMLINK:
			case ITEMLINKS:
				writeItemlinks();
				break;
			case LOCATION:
			case LOCATIONS:
				writeLocations();
				break;
			case MEMO:
			case MEMOS:
				writeMemos();
				break;
			case PART:
			case PARTS:
				writeParts();
				break;
			case PERSON:
			case PERSONS:
				writePersons();
				break;
			case RELATION:
			case RELATIONS:
				writeRelations();
				break;
			case SCENE:
			case SCENES:
				writeScenes();
				break;
			case STRAND:
			case STRANDS:
				writeStrands();
				break;
			case TAG:
			case TAGS:
				writeTags();
				break;
			case TAGLINK:
			case TAGLINKS:
				writeTaglinks();
				break;
			default:
				LOG.err("unknown type to export " + name);
				break;
		}
		if (KW.HTML.toString().equals(param.getFormat())) {
			writeText("    </table>\n");
		}
	}

	private void writeAttributes() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.ATTRIBUTE_KEY.i18n()), 10));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.ATTRIBUTE_VALUE.i18n()), 80));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		AttributeDAO dao = new AttributeDAO(session);
		List<Attribute> entities = dao.findAll();
		for (Attribute e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeCategories() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.NAME.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.SORT.i18n()), 5));
		headers.add(new ColumnHeader(I18N.getMsg("category.value"), 80));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		CategoryDAO dao = new CategoryDAO(session);
		List<Category> entities = dao.findAll();
		for (Category e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeChapters() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.PART.i18n()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.CHAPTER_CHAPTERNO.i18n()), 2));
		headers.add(new ColumnHeader(I18N.getMsg(KW.TITLE.toString()), 60));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.DATE_CREATION.i18n()), 10));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.OBJECTIVE_DATE.i18n()), 10));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.OBJECTIVE_DONE.i18n()), 10));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.OBJECTIVE_SIZE.i18n()), 6));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DESCRIPTION.toString()), 30));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 30));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		ChapterDAO dao = new ChapterDAO(session);
		List<Chapter> entities = dao.findAll();
		for (Chapter e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeGenders() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg("gender.childhood"), 3));
		headers.add(new ColumnHeader(I18N.getMsg("gender.adolescence"), 3));
		headers.add(new ColumnHeader(I18N.getMsg("gender.adulthood"), 3));
		headers.add(new ColumnHeader(I18N.getMsg("gender.retirement"), 3));
		headers.add(new ColumnHeader(I18N.getMsg("icone"), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		GenderDAO dao = new GenderDAO(session);
		List<Gender> entities = dao.findAll();
		for (Gender e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeIdeas() {
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		IdeaDAO dao = new IdeaDAO(session);
		List<Idea> entities = dao.findAll();
		//writeText("nb ideas="+entities.size());
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.STATUS.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.CATEGORY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		for (Idea e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeInternal() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.KEY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.VALUE.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		InternalDAO dao = new InternalDAO(session);
		List<Internal> entities = dao.findAll();
		for (Internal e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeItems() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.CATEGORY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.STATUS.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DESCRIPTION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		ItemDAO dao = new ItemDAO(session);
		List<Item> entities = dao.findAll();
		for (Item e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeItemlinks() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SCENE_START.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SCENE_END.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.LOCATION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.PERSON.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		ItemlinkDAO dao = new ItemlinkDAO(session);
		List<Itemlink> entities = dao.findAll();
		for (Itemlink e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeLocations() {
		//App.trace("ExportTable.writeLocations()");
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.ADRESS.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.CITY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.COUNTRY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.ALTITUDE.toString()), 8));
		headers.add(new ColumnHeader(I18N.getMsg("location.site"), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DESCRIPTION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		LocationDAO dao = new LocationDAO(session);
		List<Location> entities = dao.findAll();
		for (Location e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeMemos() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		MemoDAO dao = new MemoDAO(session);
		List<Memo> entities = dao.findAll();
		for (Memo e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeParts() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NUMBER.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg("part"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("manage.date.creation"), 10));
		headers.add(new ColumnHeader(I18N.getMsg("manage.date.objective"), 10));
		headers.add(new ColumnHeader(I18N.getMsg("manage.date.done"), 10));
		headers.add(new ColumnHeader(I18N.getMsg("manage.size.objective"), 6));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		PartDAO dao = new PartDAO(session);
		List<Part> entities = dao.findAll();
		for (Part e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writePersons() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg("gender"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("person.firstname"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("person.lastname"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("person.abbr"), 5));
		headers.add(new ColumnHeader(I18N.getMsg("person.birthday"), 10));
		headers.add(new ColumnHeader(I18N.getMsg("person.death"), 10));
		headers.add(new ColumnHeader(I18N.getMsg("person.occupation"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("person.color"), 10));
		headers.add(new ColumnHeader(I18N.getMsg(KW.CATEGORY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg("attributes"), 10));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DESCRIPTION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		PersonDAO dao = new PersonDAO(session);
		List<Person> entities = dao.findAll();
		for (Person e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeRelations() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg("person.first"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("person.second"), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SCENE_START.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SCENE_END.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg("persons"), 32));
		headers.add(new ColumnHeader(I18N.getMsg("items"), 32));
		headers.add(new ColumnHeader(I18N.getMsg("locations"), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DESCRIPTION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		RelationDAO dao = new RelationDAO(session);
		List<Relationship> entities = dao.findAll();
		for (Relationship e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeScenes() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.TITLE.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.CHAPTER.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.STRAND.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NUMBER.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DATE.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.STATUS.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.INFORMATIVE.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.DURATION.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.INTENSITY.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENE_NARRATOR.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.PERSONS.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.ITEMS.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.LOCATIONS.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.PLOTS.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.STRANDS.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENE_RELATIVETIME.i18n()), 16));
		headers.add(new ColumnHeader(I18N.getMsg("scene.relative"), 16));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENE_SUMMARY.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENE_XEDITOR.i18n()), 32));
		if (book.info.scenarioGet()) {
			headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENARIO_STAGE.i18n()), 16));
			headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENARIO_PITCH.i18n()), 16));
			headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENARIO_LOC.i18n()), 16));
			headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENARIO_MOMENT.i18n()), 16));
			headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENARIO_START.i18n()), 16));
			headers.add(new ColumnHeader(I18N.getMsg(DATA.SCENARIO_END.i18n()), 16));
		}
		headers.add(new ColumnHeader(I18N.getMsg(DATA.DESCRIPTION.i18n()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		SceneDAO dao = new SceneDAO(session);
		List<Scene> entities = dao.findAll();
		for (Scene e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeStrands() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg("strand.abbr"), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.COLOR.toString()), 8));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SORT.toString()), 10));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		StrandDAO dao = new StrandDAO(session);
		List<Strand> entities = dao.findAll();
		for (Strand e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeTags() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.CATEGORY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.STATUS.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.DESCRIPTION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		TagDAO dao = new TagDAO(session);
		List<Tag> entities = dao.findAll();
		for (Tag e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeTaglinks() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SCENE_START.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.SCENE_END.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.LOCATION.toString()), 32));
		headers.add(new ColumnHeader(I18N.getMsg(KW.PERSON.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		TaglinkDAO dao = new TaglinkDAO(session);
		List<Taglink> entities = dao.findAll();
		for (Taglink e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeEndnotes() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NAME.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg("endnote.type"), 8));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NUMBER.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		EndnoteDAO dao = new EndnoteDAO(session);
		List<Endnote> entities = dao.findAll();
		for (Endnote e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeEvents() {
		List<ColumnHeader> headers = new ArrayList<>();
		headers.add(new ColumnHeader(I18N.getMsg(KW.ID.toString()), 5));
		headers.add(new ColumnHeader(I18N.getMsg(KW.TITLE.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg("timeevent.date"), 16));
		headers.add(new ColumnHeader(I18N.getMsg("timeevent.combo.label"), 8));
		headers.add(new ColumnHeader(I18N.getMsg(KW.CATEGORY.toString()), 16));
		headers.add(new ColumnHeader(I18N.getMsg(KW.NOTES.toString()), 32));
		writeHeaderColumn(headers);
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		EventDAO dao = new EventDAO(session);
		List<Event> entities = dao.findAll();
		for (Event e : entities) {
			switch (param.getFormat()) {
				case F_ZXML:
				case F_XML:
					writeText(e.toXml());
					break;
				case F_HTML:
					writeHtml(e.toHtml());
					break;
				case F_CSV:
					writeText(e.toCsv(param.getCsvQuote(), param.getCsvQuote(), param.getCsvComma()));
					break;
				case F_TXT:
					writeText(e.toText());
					break;
				default:
					break;
			}
		}
		model.commit();
	}

	private void writeHeaderColumn(List<ColumnHeader> headers) {
		//App.trace("ExportTable.writeHeaderColumn(headers="+headers.size()+" columns");
		if (headers == null || headers.isEmpty()) {
			return;
		}
		switch (param.getFormat()) {
			case F_HTML:
				writeText("<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tr>\n");
				for (ColumnHeader header : headers) {
					writeColumn(header.getName(), header.getSize());
				}
				writeText("</tr>\n");
				break;
			case F_ZXML:
			case F_XML: //no headers
				break;
			case F_CSV:
				for (ColumnHeader header : headers) {
					writeText(param.getCsvQuote() + header.getName() + param.getCsvQuote() + param.getCsvComma());
				}
				writeText("\n");
				break;
			case F_TXT:
				for (ColumnHeader header : headers) {
					writeText(header.getName() + param.getTxtSeparator());
				}
				writeText("\n");
				break;
			default:
				break;
		}
	}

	private void writeColumn(String name, int size) {
		switch (param.getFormat()) {
			case F_HTML:
				if (size > 0) {
					writeText("    <td width=\"" + size + "%\">" + ("".equals(name) ? "&nbsp" : name) + "</td>\n");
				} else {
					writeText("    <td>" + name + "</td>\n");
				}
				break;
			case F_CSV:
				writeText("\"" + name + "\";");
				break;
			case F_TXT:
				writeText("\t" + name + "");
				break;
			default:
				break;
		}
	}

	public class ColumnHeader {

		private final String name;
		private final int size;

		ColumnHeader(String n, int s) {
			name = n;
			size = s;
		}

		public String getName() {
			return (name);
		}

		public int getSize() {
			return (size);
		}

	}
}
