package storybook.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import org.hibernate.Session;
import storybook.ctrl.ActKey;
import storybook.ctrl.Ctrl;
import static storybook.ctrl.Ctrl.PROPS.*;
import storybook.model.book.Book;
import storybook.model.hbn.SbSessionFactory;
import storybook.model.hbn.entity.AbstractEntity;
import storybook.tools.LOG;
import storybook.ui.MainFrame;

public abstract class AbstractModel {

	private static final String TT = "AbstractModel.";

	protected PropertyChangeSupport pcs;
	protected SbSessionFactory sessionFactory;
	MainFrame mainFrame;
	String name;

	public AbstractModel() {
		sessionFactory = new SbSessionFactory();
	}

	public AbstractModel(MainFrame m) {
		mainFrame = m;
		pcs = new PropertyChangeSupport(this);
		sessionFactory = new SbSessionFactory();
	}

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

	public abstract void fireAgain();

	public void testSession(String dbName) {
		//LOG.trace(TT+".testSession("+dbName+")");
		sessionFactory.init(dbName);
	}

	public void initDefault() {
		fireAgain();
	}

	public Session beginTransaction() {
		//LOG.trace(TT+".beginTransaction()");
		Session session = sessionFactory.getSession();
		session.beginTransaction();
		return session;
	}

	public Session getSession() {
		return sessionFactory.getSession();
	}

	public void commit() {
		Session session = sessionFactory.getSession();
		session.getTransaction().commit();
	}

	public void addPropertyChangeListener(PropertyChangeListener l) {
		//LOG.trace(TT+".addPropertyChangeListener("+l.toString()+")");
		pcs.addPropertyChangeListener(l);
	}

	public void removePropertyChangeListener(PropertyChangeListener l) {
		pcs.removePropertyChangeListener(l);
	}

	protected void firePropertyChange(Book.TYPE type) {
		String prop = new ActKey(type, INIT).toString();
		firePropertyChange(prop, null, EntityUtil.findEntities(mainFrame, type));
	}

	protected void firePropertyChange(Book.TYPE type, Ctrl.PROPS cmd,
	   AbstractEntity old, AbstractEntity value) {
		LOG.trace(TT + ".firePropertyChange("
		   + "type=" + type.name()
		   + ", cmd=" + cmd.name()
		   + ", old=" + (old != null ? old.toString() : "null")
		   + ", value=" + (value != null ? value.toString() : "null") + ")");
		String prop = new ActKey(type, cmd).toString();
		try {
			pcs.firePropertyChange(prop, old, value);
		} catch (Exception ex) {
			LOG.err(prop, ex);
		}
	}

	protected void firePropertyChange(String prop, Object oldValue, Object newValue) {
		/*LOG.trace(TT+".firePropertyChange(" + "prop=" + prop
				+ ", oldValue=" + (oldValue != null ? oldValue.toString() : "null")
				+ ", newValue=" + (newValue != null ? newValue.toString() : "null") + ")");*/
		try {
			pcs.firePropertyChange(prop, oldValue, newValue);
		} catch (Exception ex) {
			LOG.err(prop, ex);
		}
	}

	public SbSessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void ENTITY_Edit(AbstractEntity entity) {
		//LOG.trace(TT+".editEntity("+entity.toString()+")");
		mainFrame.showEditorAsDialog(entity);
	}

	public void closeSession() {
		sessionFactory.closeSession();
	}
}
