package com.sap.dbmtk.demo;

import java.awt.Window;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.LinkedHashMap;

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

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

import net.miginfocom.swing.MigLayout;

public class AddOrChangeAuthor
extends AddOrChangeAbstract
{
	private static final long serialVersionUID = 1L;
//	private static Logger _logger = Logger.getLogger(AddOrChangeAuthor.class);

	private static final String    NAME = "Author";
//	public  static final ImageIcon NO_PICTURE = SwingUtils.readImageIcon(DemoApp.class, "images/no_photo.jpg");
//	
//	public  static final int       MAX_PICTURE_SIZE = 50*1024;

	private int        _au_id          = -1;
	private JLabel     _au_id_lbl      = new JLabel("au_id");
	private JTextField _au_id_txt      = new JTextField(10);
	
	private JLabel     _fname_lbl      = new JLabel("First Name");
	private JTextField _fname_txt      = new JTextField(50);
	
	private JLabel     _lname_lbl      = new JLabel("Last Name");
	private JTextField _lname_txt      = new JTextField();
	
	private JLabel     _phone_lbl      = new JLabel("Phone");
	private JTextField _phone_txt      = new JTextField();
	
	private JLabel     _address_lbl    = new JLabel("Address");
	private JTextField _address_txt    = new JTextField();
	
	private JLabel     _state_lbl      = new JLabel("State");
	private JTextField _state_txt      = new JTextField();
	
	private JLabel     _city_lbl       = new JLabel("City");
	private JTextField _city_txt       = new JTextField();
	
	private JLabel     _country_lbl    = new JLabel("Country");
	private JTextField _country_txt    = new JTextField();
	
	private JLabel     _postalcode_lbl = new JLabel("Postal Code");
	private JTextField _postalcode_txt = new JTextField();
	
//	private JLabel     _picture_lbl    = new JLabel("Picture");
//	private JTextField _picture_txt    = new JTextField();
//	private JButton    _picture_but    = new JButton("...");
//	private ImageLabel _picture_ilbl   = new ImageLabel(NO_PICTURE, new Dimension(170, 220)); // boundary 170*220
//	private byte[]     _picture_ba     = null;
//	private String     _picture_lastLoaded = "";

	public AddOrChangeAuthor(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() )
		{
			_au_id_txt.setEnabled(false);
			panel.add(_au_id_lbl,  "");
			panel.add(_au_id_txt,  "growx, pushx, wrap 20");
		}

		panel.add(_fname_lbl,      "");
		panel.add(_fname_txt,      "growx, pushx, wrap");
		
		panel.add(_lname_lbl,      "");
		panel.add(_lname_txt,      "growx, pushx, wrap");
		
		panel.add(_phone_lbl,      "");
		panel.add(_phone_txt,      "growx, pushx, wrap");
		
		panel.add(_address_lbl,    "");
		panel.add(_address_txt,    "growx, pushx, wrap");
		
		panel.add(_city_lbl,       "");
		panel.add(_city_txt,       "growx, pushx, wrap");
		
		panel.add(_state_lbl,      "");
		panel.add(_state_txt,      "growx, pushx, wrap");
		
		panel.add(_country_lbl,    "");
		panel.add(_country_txt,    "growx, pushx, wrap");
		
		panel.add(_postalcode_lbl, "");
		panel.add(_postalcode_txt, "growx, pushx, wrap");

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

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

		if ( isDelete())
		{
			_fname_txt      .setEnabled(false);
			_lname_txt      .setEnabled(false);
			_phone_txt      .setEnabled(false);
			_address_txt    .setEnabled(false);
			_city_txt       .setEnabled(false);
			_state_txt      .setEnabled(false);
			_country_txt    .setEnabled(false);
			_postalcode_txt .setEnabled(false);
//			_picture_txt    .setEnabled(false);
//			_picture_but    .setEnabled(false);
		}

//		_picture_but.addActionListener(new ActionListener()
//		{
//			@Override
//			public void actionPerformed(ActionEvent e)
//			{
//				JFileChooser fc = new JFileChooser();
//				int returnVal = fc.showOpenDialog(AddOrChangeAuthor.this);
//
//				if (returnVal == JFileChooser.APPROVE_OPTION) 
//				{
//					File file = fc.getSelectedFile();
//					loadImage(file.toString());
//				} 
//			}
//		});
//		
//		_picture_txt.addActionListener(new ActionListener()
//		{
//			@Override
//			public void actionPerformed(ActionEvent e)
//			{
//				loadImage( _picture_txt.getText() );
//			}
//		});
//		_picture_txt.addFocusListener(new FocusListener()
//		{
//			@Override
//			public void focusLost(FocusEvent e)
//			{
//				loadImage( _picture_txt.getText() );
//			}
//			
//			@Override public void focusGained(FocusEvent e) {}
//		});

		return panel;
	}

//	private byte[] compressImage(BufferedImage image, float quality) 
//	throws IOException
//	{
//		// Get a ImageWriter for jpeg format.
//		Iterator<ImageWriter> writers = ImageIO.getImageWritersBySuffix("jpeg");
//		if ( !writers.hasNext() )
//			throw new IllegalStateException("No writers found");
//		ImageWriter writer = (ImageWriter) writers.next();
//
//		// Create the ImageWriteParam to compress the image.
//		ImageWriteParam param = writer.getDefaultWriteParam();
//		param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
//		param.setCompressionQuality(quality);
//		
//		// The output will be a ByteArrayOutputStream (in memory)
//		ByteArrayOutputStream bos = new ByteArrayOutputStream(32768);
//		ImageOutputStream ios = ImageIO.createImageOutputStream(bos);
//		writer.setOutput(ios);
//		writer.write(null, new IIOImage(image, null, null), param);
//		ios.flush(); // otherwise the buffer size will be zero!
//
//		return bos.toByteArray();
//
//		// From the ByteArrayOutputStream create a RenderedImage.
////		ByteArrayInputStream in = new ByteArrayInputStream(bos.toByteArray());
////		RenderedImage out = ImageIO.read(in);
////		int size = bos.toByteArray().length;
//	}
//
//	private void loadImage(String fileStr)
//	{
//		if (StringUtil.isNullOrBlank(fileStr))
//			return;
//		
//		if (fileStr.equals(_picture_lastLoaded))
//		{
//			_logger.info("loadImage(): The filename '"+fileStr+"' already seems to be loaded..." );
//			return;
//		}
//
//		try
//		{
//			File f = new File(fileStr);
//			
//			byte[] imageData = new byte[(int) f.length()];
//			DataInputStream dis = new DataInputStream(new FileInputStream(f));
//			dis.readFully(imageData);
//			dis.close();
//
//			if (f.length() > MAX_PICTURE_SIZE)
//			{
//				// convert byte array back to BufferedImage
//				InputStream in = new ByteArrayInputStream(imageData);
//				BufferedImage bImageFromConvert = ImageIO.read(in);
//
//				// Try to compress the image
//				long compSize = f.length();
//				float compQuality = 1.0f;
//				float[] compQualities = {1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f, 0.1f, 0.09f, 0.08f, 0.097f, 0.06f, 0.05f, 0.04f, 0.03f, 0.02f, 0.01f};
//				for (int cr=0; cr<compQualities.length; cr++)
//				{
//					compQuality = compQualities[cr];
//					imageData = compressImage(bImageFromConvert, compQuality);
//					compSize  = imageData.length; 
//					if (compSize < MAX_PICTURE_SIZE)
//						break;
//				}
//
//				if (compSize < MAX_PICTURE_SIZE)
//				{
//					String htmlMsg = 
//							"<html>"
//							+ "I had to <b>comress</b> the picture, it was above the limit.<br>"
//							+ "The maximum uncompressed size is "+StringUtil.bytesToHuman(MAX_PICTURE_SIZE)+"<br>" 
//							+ "<br>"
//							+ "The origin file: "+f+"<br>" 
//							+ "The origin size was "+StringUtil.bytesToHuman(f.length())+"<br>" 
//							+ "<br>"
//							+ "The used compression quality was "+compQuality+"<br>" 
//							+ "The final compressed size was "+StringUtil.bytesToHuman(compSize)+"<br>" 
//							+ "<br>"
//							+ "<i>JPEG files is preferred, other filetypes might not compress well.</i><br>"
//							+ "</html>";
//					SwingUtils.showWarnMessage(this, "Picture was compressed", htmlMsg, null);
//				}
//				else
//				{
//					String htmlMsg = 
//							"<html>"
//							+ "File size it <b>to large</b><br>"
//							+ "<b>Sorry</b> you can't use this file!<br>"
//							+ "<br>"
//							+ "The file: "+f+"<br>" 
//							+ "The origin size was "+StringUtil.bytesToHuman(f.length())+"<br>" 
//							+ "<br>"
//							+ "The result of unsuccessful compression:<br>"
//							+ "The lowest used compression quality was "+compQuality+"<br>" 
//							+ "The lowest compressed size achived was "+StringUtil.bytesToHuman(compSize)+"<br>" 
//							+ "<br>"
//							+ "<i>JPEG files is preferred, other filetypes might not compress well.</i><br>"
//							+ "<br>"
//							+ "The maximum allowed size is <b>"+StringUtil.bytesToHuman(MAX_PICTURE_SIZE)+"</b><br>" 
//							+ "<b>You need to choose another file</b><br>"
//							+ "<br>"
//							+ "</html>";
//					SwingUtils.showErrorMessage(this, "Problem", htmlMsg, null);
//					return;
//				}
//			}
//				
//			ImageIcon pic = new ImageIcon(imageData);
//
//			_picture_ilbl.setIcon(pic);
//			_picture_txt .setText(fileStr);
//			_picture_ba  = imageData;
//			
//			_picture_lastLoaded = fileStr;
//		}
//		catch (Throwable e)
//		{
//			String htmlMsg = 
//					"<html>"
//					+ "Reading file <b>failed.</b><br>"
//					+ "<br>"
//					+ "Exception: " + e + "<br>" 
//					+ "<br>"
//					+ "</html>";
//			SwingUtils.showErrorMessage(this, "Problem", htmlMsg, e);
//		}
//	}
//
//	private void loadImage(byte[] image)
//	{
//		if (image == null)
//			return;
//
//		ImageIcon pic = new ImageIcon(image);
//		_picture_ilbl.setIcon(pic);
////		_picture_ba  = image;
//	}

	private byte[] getImageFromDb(int au_id)
	{
		return getImageFromDb("{call get_author_picture(?,?)}", "au_id", au_id);
//		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call get_author_picture(?,?)}");
//		
//		stmnt.addParam( SqlStatementParam.createInParam("au_id",      Types.INTEGER, _au_id) );
//		
//		stmnt.addParam( SqlStatementParam.createOracleResultSetParam("a_cursor") );
//		
//		try
//		{
//			ResultSet rs = stmnt.executeQuery(getConnection());
//			
//			byte[] ba = null;
//			while (rs.next())
//			{
//				ba = rs.getBytes(1);
//			}
//			rs.close();
//			return ba;
//		}
//		catch (SQLException e)
//		{
//			SqlStatement.showErrorMessage(e, stmnt, getOwner(), "Getting Author Picture <b>failed.</b>");
//			return null;
//		}
	}

	@Override
	public void setFields(GTable table, int vrow)
	{
		_au_id          = table.getValueAsInteger(vrow, "au_id", false);
		_au_id_txt      .setText(_au_id+"");

		_fname_txt      .setText(table.getValueAsString(vrow, "first_name", false));
		_lname_txt      .setText(table.getValueAsString(vrow, "last_name",  false));
		_phone_txt      .setText(table.getValueAsString(vrow, "phone",      false));
		_address_txt    .setText(table.getValueAsString(vrow, "address",    false));
		_city_txt       .setText(table.getValueAsString(vrow, "city",       false));
		_state_txt      .setText(table.getValueAsString(vrow, "state",      false));
		_country_txt    .setText(table.getValueAsString(vrow, "country",    false));
		_postalcode_txt .setText(table.getValueAsString(vrow, "postalcode", false));
		
		byte[] ba = getImageFromDb(_au_id);
		loadImage(ba);
	}


	public String getFirstName()  { return getStringValue(_fname_txt     ); }
	public String getLastName()   { return getStringValue(_lname_txt     ); }
	public String getPhone()      { return getStringValue(_phone_txt     ); }
	public String getAddress()    { return getStringValue(_address_txt   ); }
	public String getCity()       { return getStringValue(_city_txt      ); }
	public String getState()      { return getStringValue(_state_txt     ); }
	public String getCountry()    { return getStringValue(_country_txt   ); }
	public String getPostalcode() { return getStringValue(_postalcode_txt); }
//	public byte[] getPicture()    { return _picture_ba; }

	@Override
	public boolean doInsert()
	{
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call insert_author(?, ?, ?, ?, ?, ?, ?, ?, ?)}");
	    
		stmnt.addParam( SqlStatementParam.createInParam("first_name", Types.VARCHAR, getFirstName()  ) );
		stmnt.addParam( SqlStatementParam.createInParam("last_name",  Types.VARCHAR, getLastName()   ) );
		stmnt.addParam( SqlStatementParam.createInParam("phone",      Types.VARCHAR, getPhone()      ) );
		stmnt.addParam( SqlStatementParam.createInParam("address",    Types.VARCHAR, getAddress()    ) );
		stmnt.addParam( SqlStatementParam.createInParam("city",       Types.VARCHAR, getCity()       ) );
		stmnt.addParam( SqlStatementParam.createInParam("state",      Types.VARCHAR, getState()      ) );
		stmnt.addParam( SqlStatementParam.createInParam("country",    Types.VARCHAR, getCountry()    ) );
		stmnt.addParam( SqlStatementParam.createInParam("postalcode", Types.VARCHAR, getPostalcode() ) );
		stmnt.addParam( SqlStatementParam.createInParam("picture",    Types.BLOB,    getPicture()    ) );

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

//		boolean exec2 = true;
//		if (exec1 && _picture_ba != null)
//		{
//			stmnt = new SqlStatement(Type.CALLABLE, "{call gs_blob_proc1(?, ?)}");
//			stmnt.addParam( SqlStatementParam.createInParam("au_id",   Types.INTEGER, _au_id      ) );
//			stmnt.addParam( SqlStatementParam.createInParam("picture", Types.BLOB,    _picture_ba ) );
//			exec2 = stmnt.execute(getConnection(), _owner, "Adding "+NAME+" information <b>failed.</b>");
//		}
//		
//		return exec1 && exec2;
	}

	@Override
	public boolean doUpdate()
	{
		SqlStatement stmnt = null;
		Connection conn = null;

		try
		{
			conn = getConnection();

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

			//----------------------------------------------
			// FIRST do NORMAL DATA
			stmnt = new SqlStatement(Type.CALLABLE, "{call update_author(?, ?, ?, ?, ?, ?, ?, ?, ?)}");
		    
			stmnt.addParam( SqlStatementParam.createInParam("au_id",      Types.INTEGER, _au_id) );

			stmnt.addParam( SqlStatementParam.createInParam("first_name", Types.VARCHAR, getFirstName()  ) );
			stmnt.addParam( SqlStatementParam.createInParam("last_name",  Types.VARCHAR, getLastName()   ) );
			stmnt.addParam( SqlStatementParam.createInParam("phone",      Types.VARCHAR, getPhone()      ) );
			stmnt.addParam( SqlStatementParam.createInParam("address",    Types.VARCHAR, getAddress()    ) );
			stmnt.addParam( SqlStatementParam.createInParam("city",       Types.VARCHAR, getCity()       ) );
			stmnt.addParam( SqlStatementParam.createInParam("state",      Types.VARCHAR, getState()      ) );
			stmnt.addParam( SqlStatementParam.createInParam("country",    Types.VARCHAR, getCountry()    ) );
			stmnt.addParam( SqlStatementParam.createInParam("postalcode", Types.VARCHAR, getPostalcode() ) );

//			stmnt.execute(getConnectionProvider());
			stmnt.executeWithGuiProgress( getConnectionProvider(), getOwner() );

		
			//----------------------------------------------
			// THEN DO PICTURE
			if (getPicture() != null)
			{
				stmnt = new SqlStatement(Type.CALLABLE, "{call update_author_picture(?, ?)}");
				
				stmnt.addParam( SqlStatementParam.createInParam("au_id",      Types.INTEGER, _au_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 Author Dialog");
			}
		}
	}

	@Override
	public boolean doDelete()
	{
		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call delete_author(?)}");
		
		stmnt.addParam( SqlStatementParam.createInParam("au_id",   Types.INTEGER, _au_id) );

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


//	public static HashMap<String, Integer> getAuthorsLookup(Window owner, ConnectionProvider connProvider)
//	{
//		LinkedHashMap<String, Integer> map = new LinkedHashMap<String, Integer>(); 
//		
////		String sql = "select au_fname||' '||au_lname as author_name, au_id from authors \n";
//
//		SqlStatement stmnt = new SqlStatement(Type.CALLABLE, "{call get_authors_lookup(?)}");
//		stmnt.addParam( SqlStatementParam.createOracleResultSetParam("a_cursor") );
//
//		try
//		{
//			ResultSet rs = stmnt.executeQuery(connProvider);
//			int rowc = 0;
//			while(rs.next())
//			{
//				rowc++;
//				map.put(rs.getString(1), rs.getInt(2));
//			}
//			SqlTraceWindow.getInstance().addRowcount( rowc );
//
//			SqlStatement.putWarningMessages(connProvider, null, rs);
//			rs.close();
//		}
//		catch (SQLException e)
//		{
//			SqlStatement.showErrorMessage(e, stmnt, owner, "Getting Author (name,id) <b>failed.</b>");
//		}
//		
//		return map;
//	}
}
