package com.sap.dbmtk.demo;

import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.swingx.JXDatePicker;

import com.sap.dbmtk.demo.SqlStatement.Type;
import com.sap.dbmtk.demo.ui.GTable;
import com.sap.dbmtk.demo.utils.DbUtils;

public class AddOrChangeTitle
extends AddOrChangeAbstract
implements ActionListener, KeyListener, FocusListener
{
	private static final long serialVersionUID = 1L;

	private static final String NAME = "Title";

	private int                 _title_id        = -1;
	private JLabel              _title_id_lbl    = new JLabel("title_id");
	private JTextField          _title_id_txt    = new JTextField(10);

	private JLabel              _title_lbl       = new JLabel("Title");
	private JTextField          _title_txt       = new JTextField(50);
	
	private JLabel              _type_lbl        = new JLabel("Type");
	private JTextField          _type_txt        = new JTextField();
	
	private JLabel              _isbn_lbl        = new JLabel("ISBN");
	private JTextField          _isbn_txt        = new JTextField();
	
	private JLabel              _pubdate_lbl     = new JLabel("Publication Date");
//	private JXDateTimePicker    _pubdate_dtp     = new JXDateTimePicker();
	private JXDatePicker        _pubdate_dtp     = new JXDatePicker();
	
	private JLabel              _price_lbl       = new JLabel("Price");
//	private JFormattedTextField _price_txt       = new JFormattedTextField(NumberFormat.getNumberInstance());
	private JTextField          _price_txt       = new JTextField();

	private JLabel              _advance_lbl     = new JLabel("Advance");
//	private JFormattedTextField _advance_txt     = new JFormattedTextField(NumberFormat.getNumberInstance());
	private JTextField          _advance_txt     = new JTextField();
	
	private JLabel              _total_sales_lbl = new JLabel("Total Sales");
//	private JFormattedTextField _total_sales_txt = new JFormattedTextField(NumberFormat.getNumberInstance());
	private JTextField          _total_sales_txt = new JTextField();
	
	private JLabel              _notes_lbl       = new JLabel("Notes");
	private JTextField          _notes_txt       = new JTextField();
	
	private JLabel              _contract_lbl    = new JLabel("Contract");
//	private JFormattedTextField _contract_txt    = new JFormattedTextField(NumberFormat.getNumberInstance());
	private JTextField          _contract_txt    = new JTextField();
	
	private JLabel              _author_lbl      = new JLabel("Author");
//	private JComboBox           _author_cbx      = new JComboBox();
	private JLabel              _authorFn_lbl    = new JLabel("First Name");
	private JLabel              _authorLn_lbl    = new JLabel("Last Name");
	private JTextField          _authorFn_txt    = new JTextField();
	private JTextField          _authorLn_txt    = new JTextField();
	private JButton             _author_but      = new JButton("...");
	
	private JLabel              _publisher_lbl   = new JLabel("Publisher");
//	private JComboBox           _publisher_cbx   = new JComboBox();
	private JTextField          _publisher_txt   = new JTextField();
	private JButton             _publisher_but   = new JButton("...");
	
//	private final static String NO_ROW_SELECTED = "<none>";
//
//	private HashMap<String, Integer> _authorsMap    = new LinkedHashMap<String, Integer>();
//	private HashMap<String, Integer> _publishersMap = new LinkedHashMap<String, Integer>();

	public AddOrChangeTitle(Window owner, ConnectionProvider connProvider, OpType opType)
	{
		super(NAME, owner, connProvider, opType);
		super.init();
	}

	@Override
	public JPanel createPanel()
	{
		JPanel panel = new JPanel();
		panel.setLayout(new MigLayout());

		if ( isUpdate() || isDelete() )
		{
			_title_id_txt.setEnabled(false);
			panel.add(_title_id_lbl,  "");
			panel.add(_title_id_txt,  "growx, pushx, wrap 20");
		}

		panel.add(_title_lbl,       "");
		panel.add(_title_txt,       "growx, pushx, wrap");
		
		panel.add(_type_lbl,        "");
		panel.add(_type_txt,        "growx, pushx, wrap");
		
		panel.add(_isbn_lbl,        "");
		panel.add(_isbn_txt,        "growx, pushx, wrap");
		
		panel.add(_pubdate_lbl,     "");
		panel.add(_pubdate_dtp,     "growx, pushx, wrap");

		panel.add(_price_lbl,       "");
		panel.add(_price_txt,       "growx, pushx, wrap");
		
		panel.add(_advance_lbl,     "");
		panel.add(_advance_txt,     "growx, pushx, wrap");
		
		panel.add(_total_sales_lbl, "");
		panel.add(_total_sales_txt, "growx, pushx, wrap");
		
		panel.add(_notes_lbl,       "");
		panel.add(_notes_txt,       "growx, pushx, wrap");
		
		panel.add(_contract_lbl,    "");
		panel.add(_contract_txt,    "growx, pushx, wrap");
		
		panel.add(_author_lbl,      "");
//		panel.add(_author_cbx,      "growx, pushx, wrap");
//		panel.add(_author_txt,      "split, growx, pushx");
		panel.add(_authorFn_lbl,    "split");
		panel.add(_authorFn_txt,    "growx, pushx");
		panel.add(_authorLn_lbl,    "");
		panel.add(_authorLn_txt,    "growx, pushx");
		panel.add(_author_but,      "wrap");

		panel.add(_publisher_lbl,   "");
//		panel.add(_publisher_cbx,   "growx, pushx, wrap");
		panel.add(_publisher_txt,   "split, growx, pushx");
		panel.add(_publisher_but,   "wrap");

		panel.add(_picture_lbl,    "");
		panel.add(_picture_txt,    "split, growx, pushx");
		panel.add(_picture_but,    "wrap 20");

		panel.add(_picture_ilbl,   "center, width 85:170:400, height 220:220:220, gapright 10, dock west, wrap");

		if ( isDelete())
		{
			_title_txt       .setEnabled(false);
			_type_txt        .setEnabled(false);
			_isbn_txt        .setEnabled(false);
			_pubdate_dtp     .setEnabled(false);
			_price_txt       .setEnabled(false);
			_advance_txt     .setEnabled(false);
			_total_sales_txt .setEnabled(false);
			_notes_txt       .setEnabled(false);
			_contract_txt    .setEnabled(false);
			_authorFn_txt    .setEnabled(false);
			_authorLn_txt    .setEnabled(false);
			_author_but      .setEnabled(false);
			_publisher_txt   .setEnabled(false);
			_publisher_but   .setEnabled(false);
		}     

//		_authorsMap    = AddOrChangeAuthor   .getAuthorsLookup(_owner, getConnectionProvider());
//		_publishersMap = AddOrChangePublisher.getPublishersLookup(_owner, getConnectionProvider());
//
//		SqlStatement.showWarningMessages(getConnectionProvider(), getOwner(), "Warning messages when getting: getAuthorsLookup() or getPublishersLookup()");
//		
//		_author_cbx.addItem(NO_ROW_SELECTED);
//		for (String key : _authorsMap.keySet())
//			_author_cbx.addItem(key);
//
//		_publisher_cbx.addItem(NO_ROW_SELECTED);
//		for (String key : _publishersMap.keySet())
//			_publisher_cbx.addItem(key);
		

		_authorFn_txt    .addActionListener(this);
		_authorLn_txt    .addActionListener(this);
		_author_but      .addActionListener(this);
		_publisher_txt   .addActionListener(this);
		_publisher_but   .addActionListener(this);

		_title_txt       .addKeyListener(this);
		_isbn_txt        .addKeyListener(this);
		_price_txt       .addKeyListener(this);
		_advance_txt     .addKeyListener(this);
		_total_sales_txt .addKeyListener(this);
		_contract_txt    .addKeyListener(this);

		_title_txt       .addFocusListener(this);
		_isbn_txt        .addFocusListener(this);
		_price_txt       .addFocusListener(this);
		_advance_txt     .addFocusListener(this);
		_total_sales_txt .addFocusListener(this);
		_contract_txt    .addFocusListener(this);

		return panel;
	}

	//-------------------------------------------------
	// BEGIN: Implementing: ActionListener
	//-------------------------------------------------
	@Override
	public void actionPerformed(ActionEvent e)
	{
		Object source = e.getSource();
		
		if (_publisher_txt.equals(source) || _publisher_but.equals(source))
		{
			showPublisherPickTable();
		}

		if (_authorFn_txt.equals(source) || _authorLn_txt.equals(source) || _author_but.equals(source))
		{
			showAuthorPickTable();
		}

		validateContent();
	}
	//-------------------------------------------------
	// END: Implementing: ActionListener
	//-------------------------------------------------

	//-------------------------------------------------
	// BEGIN: Implementing: KeyListener
	//-------------------------------------------------
	@Override
	public void keyTyped(KeyEvent e)
	{
	}
	
	@Override
	public void keyReleased(KeyEvent e)
	{
		validateContent();
	}
	
	@Override
	public void keyPressed(KeyEvent e)
	{
	}
	//-------------------------------------------------
	// END: Implementing: KeyListener
	//-------------------------------------------------

	//-------------------------------------------------
	// BEGIN: Implementing: FocusListener
	//-------------------------------------------------
	@Override
	public void focusLost(FocusEvent e)
	{
		validateContent();
	}
	
	@Override
	public void focusGained(FocusEvent e)
	{
		Object source = e.getSource();

		if ( source instanceof JTextField )
		{
			JTextField field = (JTextField)e.getSource();
			field.selectAll();
		}
	}
	//-------------------------------------------------
	// END: Implementing: FocusListener
	//-------------------------------------------------

	@Override
	public String getProblemText()
	{
		if ( isInsert() || isUpdate() )
		{
			// Title
			if ( _title_txt.getText().trim().length() == 0 )
			{
				return "Title Name must be entered"; 
			}

			// ISBN
			if ( _isbn_txt.getText().trim().length() == 0 )
			{
				return "ISBN must be entered"; 
			}

			// Price 
			if ( _price_txt.getText().trim().length() > 0 )
			{
    			try { new BigDecimal(_price_txt.getText()); }
    			catch(NumberFormatException nfe) { return "Price must be a Number"; }
			}

			// Advance
			if ( _advance_txt.getText().trim().length() > 0 )
			{
				try { new BigDecimal(_advance_txt.getText()); }
				catch(NumberFormatException nfe) { return "Advance must be a Number"; }
			}

			// TotalSales 
			if ( _total_sales_txt.getText().trim().length() > 0 )
			{
				try { new Integer(_total_sales_txt.getText()); }
				catch(NumberFormatException nfe) { return "Total Sales must be a Integer"; }
			}

			// Contract 
			if ( _contract_txt.getText().trim().length() > 0 )
			{
				try { new Integer(_contract_txt.getText()); }
				catch(NumberFormatException nfe) { return "Contract must be a Integer"; }
			}
		}
		return null;
	}

//	private String getAuthorNameForId(int id)
//	{
//		for (String key : _authorsMap.keySet())
//		{
//			if (_authorsMap.get(key) == id)
//				return key;
//		}
//		return "not found id="+id;
//	}
//
//	private String getPublisherNameForId(int id)
//	{
//		for (String key : _publishersMap.keySet())
//		{
//			if (_publishersMap.get(key) == id)
//				return key;
//		}
//		return "not found id="+id;
//	}

	private byte[] getImageFromDb(int au_id)
	{
		return getImageFromDb("{call ${PKG:titles_pkg}get_title_picture(?,?)}", "title_id", _title_id);
	}

	@Override
	public void setFields(GTable table, int vrow)
	{
		_title_id       = table.getValueAsInteger(vrow, "title_id", false);
		_title_id_txt   .setText(""+_title_id);

		_title_txt      .setText     (table.getValueAsString    (vrow, "title",       false));
		_type_txt       .setText     (table.getValueAsString    (vrow, "type",        false));
		_isbn_txt       .setText     (table.getValueAsString    (vrow, "isbn",        false));
//		_pubdate_dtp    .setTimestamp(table.getValueAsTimestamp (vrow, "pubdate",     false));
		_pubdate_dtp    .setDate     (table.getValueAsTimestamp (vrow, "pubdate",     false));
//		_price_txt      .setValue    (table.getValueAsBigDecimal(vrow, "price",       false));
//		_advance_txt    .setValue    (table.getValueAsBigDecimal(vrow, "advance",     false));
//		_total_sales_txt.setValue    (table.getValueAsBigDecimal(vrow, "total_sales", false));
//		_notes_txt      .setText     (table.getValueAsString    (vrow, "notes",       false));
//		_contract_txt   .setValue    (table.getValueAsBigDecimal(vrow, "contract",    false));
		_price_txt      .setText     (table.getValueAsString    (vrow, "price",       false));
		_advance_txt    .setText     (table.getValueAsString    (vrow, "advance",     false));
		_total_sales_txt.setText     (table.getValueAsString    (vrow, "total_sales", false));
		_notes_txt      .setText     (table.getValueAsString    (vrow, "notes",       false));
		_contract_txt   .setText     (table.getValueAsString    (vrow, "contract",    false));

		Integer au_id  = table.getValueAsInteger(vrow, "au_id",  false);
		Integer pub_id = table.getValueAsInteger(vrow, "pub_id", false);

//		_author_cbx   .setSelectedItem( au_id  == null ? NO_ROW_SELECTED : getAuthorNameForId(au_id) );
//		_publisher_cbx.setSelectedItem( pub_id == null ? NO_ROW_SELECTED : getPublisherNameForId(pub_id) );

		getAuthorById   (au_id);
		getPublisherById(pub_id);
		
		byte[] ba = getImageFromDb(_title_id);
		loadImage(ba);
		
		validateContent();
	}


	public String     getTitleName()   { return getStringValue    (_title_txt      ); }
	public String     getType()        { return getStringValue    (_type_txt       ); }
	public String     getIsbn()        { return getStringValue    (_isbn_txt       ); }
//	public Timestamp  getPubDate()     { return                    _pubdate_dtp.getTimestamp(); }
	public Timestamp  getPubDate()     { return _pubdate_dtp.getDate()==null ? null : new Timestamp(_pubdate_dtp.getDate().getTime()); }
	public BigDecimal getPrice()       { return getBigDecimalValue(_price_txt      ); }
	public BigDecimal getAdvance()     { return getBigDecimalValue(_advance_txt    ); }
	public BigDecimal getTotalSales()  { return getBigDecimalValue(_total_sales_txt); }
	public String     getNotes()       { return getStringValue    (_notes_txt      ); }
	public BigDecimal getContract()    { return getBigDecimalValue(_contract_txt   ); }

	public String     getAuthorFName() { return getStringValue    (_authorFn_txt   ); }
	public String     getAuthorLName() { return getStringValue    (_authorLn_txt   ); }
	public String     getPubName()     { return getStringValue    (_publisher_txt  ); }

//	public Integer getAuthorId()    
//	{ 
//		String name = _author_cbx.getSelectedItem() + "";
//		if (NO_ROW_SELECTED.equals(name))
//			return null;
//		return _authorsMap.get(name);
//	}
//
//	public Integer getPublisherId() 
//	{ 
//		String name = _publisher_cbx.getSelectedItem() + "";
//		if (NO_ROW_SELECTED.equals(name))
//			return null;
//		return _publishersMap.get(name);
//	}

	private void getAuthorById(int id)
	{
//		SqlStatement stmnt = new SqlStatement(Type.LANGUAGE, "select au_fname as first_name, au_lname as last_name, au_id from authors where au_id = "+id);
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call get_author_by_id(?,?)}");
		stmnt.addParam( SqlStatementParam.createInParam("p_au_id", Types.INTEGER, id) );
		stmnt.addParam( SqlStatementParam.createOracleResultSetParam("a_cursor") );

		try
		{
			ResultSet rs = stmnt.executeQuery(getConnectionProvider());
			int rowc = 0;
			while(rs.next())
			{
				rowc++;
				_authorFn_txt.setText( rs.getString(1) );
				_authorLn_txt.setText( rs.getString(2) );
			}
			SqlTraceWindow.getInstance().addRowcount( rowc );

			SqlStatement.putWarningMessages(getConnectionProvider(), null, rs);
			rs.close();
		}
		catch (SQLException e)
		{
			SqlStatement.showErrorMessage(e, stmnt, getOwner(), "Getting Author by ID <b>failed.</b>");
		}
	}
	private void getPublisherById(int id)
	{
//		SqlStatement stmnt = new SqlStatement(Type.LANGUAGE, "select pub_name, pub_id from publishers where pub_id = "+id);
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call get_publisher_by_id(?,?)}");
		stmnt.addParam( SqlStatementParam.createInParam("p_pub_id", Types.INTEGER, id) );
		stmnt.addParam( SqlStatementParam.createOracleResultSetParam("a_cursor") );

		try
		{
			ResultSet rs = stmnt.executeQuery(getConnectionProvider());
			int rowc = 0;
			while(rs.next())
			{
				rowc++;
				_publisher_txt.setText( rs.getString(1) );
			}
			SqlTraceWindow.getInstance().addRowcount( rowc );

			SqlStatement.putWarningMessages(getConnectionProvider(), null, rs);
			rs.close();
		}
		catch (SQLException e)
		{
			SqlStatement.showErrorMessage(e, stmnt, getOwner(), "Getting Publisher by ID <b>failed.</b>");
		}
	}

	private void showAuthorPickTable()
	{
		String au_fname = _authorFn_txt.getText();
		String au_lname = _authorLn_txt.getText();

		// Get Order Details (if its Delete or Update)
//		SqlStatement stmnt = new SqlStatement(Type.LANGUAGE, "select au_fname as first_name, au_lname as last_name, au_id from authors where au_fname like '"+au_fname+"%' or au_lname like '"+au_lname+"%' order by au_fname, au_lname");
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call get_authors_lookup(?,?,?)}");
		stmnt.addParam( SqlStatementParam.createInParam("first_name", Types.VARCHAR, au_fname) );
		stmnt.addParam( SqlStatementParam.createInParam("last_name",  Types.VARCHAR, au_lname) );
		stmnt.addParam( SqlStatementParam.createOracleResultSetParam("a_cursor") );

		SqlPickList pickList = new SqlPickList(this, getConnectionProvider(), stmnt, "title-AuthorName");

		boolean setValues = false;
		if (pickList.getRowCount() == 1)
			setValues = true;
		else
		{
			pickList.setVisible(true);
			if (pickList.wasOkPressed())
				setValues = true;
		}
		if (setValues)
		{
			_authorFn_txt.setText(pickList.getSelectedValuesAsString("first_name"));
			_authorLn_txt.setText(pickList.getSelectedValuesAsString("last_name"));
			
			// FOCUS: Next field 
			//_xxx_txt.requestFocus();
		}
	}
	
	private void showPublisherPickTable()
	{
		String pub_name = _publisher_txt.getText();

		// Get Order Details (if its Delete or Update)
//		SqlStatement stmnt = new SqlStatement(Type.LANGUAGE, "select pub_name, pub_id from publishers where pub_name like '"+pub_name+"%' order by pub_name");
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call get_publishers_lookup(?,?)}");
		stmnt.addParam( SqlStatementParam.createInParam("pub_name", Types.VARCHAR, pub_name) );
		stmnt.addParam( SqlStatementParam.createOracleResultSetParam("a_cursor") );

		SqlPickList pickList = new SqlPickList(this, getConnectionProvider(), stmnt, "title-PubName");

		boolean setValues = false;
		if (pickList.getRowCount() == 1)
			setValues = true;
		else
		{
			pickList.setVisible(true);
			if (pickList.wasOkPressed())
				setValues = true;
		}
		if (setValues)
		{
			_publisher_txt.setText(pickList.getSelectedValuesAsString("pub_name"));
			
			// FOCUS: Next field 
			//_xxx_txt.requestFocus();
		}
	}
	
	@Override
	public boolean doInsert()
	{
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call ${PKG:titles_pkg}insert_title(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
	    
		stmnt.addParam( SqlStatementParam.createInParam("title",         Types.VARCHAR,   getTitleName()   ) );
		stmnt.addParam( SqlStatementParam.createInParam("type",          Types.VARCHAR,   getType()        ) );
		stmnt.addParam( SqlStatementParam.createInParam("price",         Types.NUMERIC,   getPrice()       ) );
		stmnt.addParam( SqlStatementParam.createInParam("advance",       Types.NUMERIC,   getAdvance()     ) );
		stmnt.addParam( SqlStatementParam.createInParam("total_sales",   Types.INTEGER,   getTotalSales()  ) );
		stmnt.addParam( SqlStatementParam.createInParam("notes",         Types.VARCHAR,   getNotes()       ) );
		stmnt.addParam( SqlStatementParam.createInParam("pubdate",       Types.TIMESTAMP, getPubDate()     ) );
		stmnt.addParam( SqlStatementParam.createInParam("contract",      Types.INTEGER,   getContract()    ) );
		stmnt.addParam( SqlStatementParam.createInParam("isbn",          Types.VARCHAR,   getIsbn()        ) );
//		stmnt.addParam( SqlStatementParam.createInParam("au_id",         Types.INTEGER,   getAuthorId()    ) );
//		stmnt.addParam( SqlStatementParam.createInParam("pub_id",        Types.INTEGER,   getPublisherId() ) );
		stmnt.addParam( SqlStatementParam.createInParam("au_first_name", Types.VARCHAR,   getAuthorFName() ) );
		stmnt.addParam( SqlStatementParam.createInParam("au_last_name",  Types.VARCHAR,   getAuthorLName() ) );
		stmnt.addParam( SqlStatementParam.createInParam("pub_name",      Types.VARCHAR,   getPubName()     ) );
		stmnt.addParam( SqlStatementParam.createInParam("picture",       Types.BLOB,      getPicture()    ) );

		return stmnt.execute(getConnectionProvider(), _owner, "Adding "+NAME+" information <b>failed.</b>");
	}

//	@Override
//	public boolean doUpdate()
//	{
//		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call update_title(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
//	    
//		stmnt.addParam( SqlStatementParam.createInParam("title_id",    Types.INTEGER,   _title_id) );
//
//		stmnt.addParam( SqlStatementParam.createInParam("title",       Types.VARCHAR,   getTitleName()   ) );
//		stmnt.addParam( SqlStatementParam.createInParam("type",        Types.VARCHAR,   getType()        ) );
//		stmnt.addParam( SqlStatementParam.createInParam("price",       Types.NUMERIC,   getPrice()       ) );
//		stmnt.addParam( SqlStatementParam.createInParam("advance",     Types.NUMERIC,   getAdvance()     ) );
//		stmnt.addParam( SqlStatementParam.createInParam("total_sales", Types.INTEGER,   getTotalSales()  ) );
//		stmnt.addParam( SqlStatementParam.createInParam("notes",       Types.VARCHAR,   getNotes()       ) );
//		stmnt.addParam( SqlStatementParam.createInParam("pubdate",     Types.TIMESTAMP, getPubDate()     ) );
//		stmnt.addParam( SqlStatementParam.createInParam("contract",    Types.INTEGER,   getContract()    ) );
//		stmnt.addParam( SqlStatementParam.createInParam("isbn",        Types.VARCHAR,   getIsbn()        ) );
//		stmnt.addParam( SqlStatementParam.createInParam("au_id",       Types.INTEGER,   getAuthorId()    ) );
//		stmnt.addParam( SqlStatementParam.createInParam("pub_id",      Types.INTEGER,   getPublisherId() ) );
//
//		return stmnt.execute(getConnectionProvider(), _owner, "Updating "+NAME+" information <b>failed.</b>");
//	}
	@Override
	public boolean doUpdate()
	{
		SqlStatement stmnt = null;
		Connection conn = null;

		try
		{
			conn = getConnection();

			// Set to "MANUAL" transaction mode, If we are in AutoCommit COMMIT at start
			if (getConnectionProvider().isAutoCommitEnabledAtConnect())
				DbUtils.setAutoCommit(conn, null, getOwner(), false, "Add or Change Title Dialog"); //conn.setAutoCommit(false);

			//----------------------------------------------
			// FIRST do NORMAL DATA
			stmnt = new SqlStatement(Type.CALLABLE, "{call ${PKG:titles_pkg}update_title(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
		    
			stmnt.addParam( SqlStatementParam.createInParam("title_id",      Types.INTEGER,   _title_id) );
	
			stmnt.addParam( SqlStatementParam.createInParam("title",         Types.VARCHAR,   getTitleName()   ) );
			stmnt.addParam( SqlStatementParam.createInParam("type",          Types.VARCHAR,   getType()        ) );
			stmnt.addParam( SqlStatementParam.createInParam("price",         Types.NUMERIC,   getPrice()       ) );
			stmnt.addParam( SqlStatementParam.createInParam("advance",       Types.NUMERIC,   getAdvance()     ) );
			stmnt.addParam( SqlStatementParam.createInParam("total_sales",   Types.INTEGER,   getTotalSales()  ) );
			stmnt.addParam( SqlStatementParam.createInParam("notes",         Types.VARCHAR,   getNotes()       ) );
			stmnt.addParam( SqlStatementParam.createInParam("pubdate",       Types.TIMESTAMP, getPubDate()     ) );
			stmnt.addParam( SqlStatementParam.createInParam("contract",      Types.INTEGER,   getContract()    ) );
			stmnt.addParam( SqlStatementParam.createInParam("isbn",          Types.VARCHAR,   getIsbn()        ) );
//			stmnt.addParam( SqlStatementParam.createInParam("au_id",         Types.INTEGER,   getAuthorId()    ) );
//			stmnt.addParam( SqlStatementParam.createInParam("pub_id",        Types.INTEGER,   getPublisherId() ) );
			stmnt.addParam( SqlStatementParam.createInParam("au_first_name", Types.VARCHAR,   getAuthorFName() ) );
			stmnt.addParam( SqlStatementParam.createInParam("au_last_name",  Types.VARCHAR,   getAuthorLName() ) );
			stmnt.addParam( SqlStatementParam.createInParam("pub_name",      Types.VARCHAR,   getPubName()     ) );
	
//			stmnt.execute(getConnectionProvider());
			stmnt.executeWithGuiProgress( getConnectionProvider(), getOwner() );


			//----------------------------------------------
			// THEN DO PICTURE
			if (getPicture() != null)
			{
    			stmnt = new SqlStatement(Type.CALLABLE, "{call ${PKG:titles_pkg}update_title_picture(?, ?)}");
    		    
    			stmnt.addParam( SqlStatementParam.createInParam("title_id",   Types.INTEGER, _title_id       ) );
    			stmnt.addParam( SqlStatementParam.createInParam("picture",    Types.BLOB,    getPicture()    ) );
    
//    			stmnt.execute(getConnectionProvider());
    			stmnt.executeWithGuiProgress( getConnectionProvider(), getOwner() );
			}

			// Now COMMIT the above
			conn.commit();

			return true;
		}
//		catch (SQLException ex)
		catch (Throwable ex)
		{
			SqlStatement.showErrorMessage(ex, stmnt, _owner, "Updating "+NAME+" information <b>failed.</b>");

			// ROLLBACK
			if (conn != null)
			{
				try { conn.rollback();	}
				catch (SQLException ex2) { SqlStatement.showErrorMessage(ex2, stmnt, _owner, "Error when rolling back the executed statements"); }
			}

			return false;
		}
		finally
		{
			// RESTORE AUTOCOMMIT, If we are in AutoCommit COMMIT at start
			if ( conn != null && getConnectionProvider().isAutoCommitEnabledAtConnect() )
			{
//    			try { conn.setAutoCommit(true);	}
//    			catch (SQLException ex2) { SqlStatement.showErrorMessage(ex2, stmnt, _owner, "Setting conn to 'autocommit' <b>failed.</b>"); }
				DbUtils.setAutoCommit(conn, null, getOwner(), true, "Add or Change Title Dialog");
			}
		}
	}

	@Override
	public boolean doDelete()
	{
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call ${PKG:titles_pkg}delete_title(?)}");
	    
		stmnt.addParam( SqlStatementParam.createInParam("title_id",    Types.INTEGER,   _title_id) );

		return stmnt.execute(getConnectionProvider(), _owner, "Deleting "+NAME+" information <b>failed.</b>");
	}
}
