package siprp.medicina.processo.mail;

import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.html.HTMLEditorKit;

import com.evolute.utils.images.ImageIconLoader;
import com.evolute.utils.tables.BaseTable;
import com.evolute.utils.tables.VectorTableModel;
import com.evolute.utils.ui.CustomJDialog;
import com.evolute.utils.ui.DialogException;

public class MailDialog extends CustomJDialog
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	protected StyledEditorKit.FontSizeAction FONT_SIZE_ACTIONS[];
	protected int FONT_SIZES[];
	
	protected JFrame owner;
	
	protected JTextField toText;
	protected JTextField bccText;
	protected JTextField subjectText;
	protected BaseTable attachmentsTable;
	protected VectorTableModel attachmentsModel;
	protected JTextPane bodyPane;
	
	protected Action removeAttachmentAction;
	
	public static void main( String args[] )
		throws Exception
	{
		MailDialog mailDialog = new MailDialog( null );
		mailDialog.setTo( "fredPalma@netcabo.pt" );
		mailDialog.setBcc( "fpalma@evolute.pt" );
		mailDialog.setSubject( "SIPRP - Marca\u00E7\u00E3o de consulta de 'Frederico Palma'" );
		mailDialog.setMessage(
				"<p>"
				+ "<font size=\"3\" face=\"Arial\">Vimos pelo presente informar que 'Frederico Palma' dever&#xe1; comparecer "
				+ "nas nossas instala&#xe7;&#xf5;es para a realiza&#xe7;&#xe3;o da consulta de Medicina "
				+ "do Trabalho, no dia '<b>10-01-2008</b>', pelas <b>08H30</b>. </font>"
				+ "</p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">Solicitamos, tamb&#xe9;m, que o colaborador seja portador do <b>Boletim de Vacinas</b> e "
				+ "dos <b>&#xfa;ltimos exames complementares</b> realizados.</font>"
				+ "</p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">Caso n&#xe3;o seja poss&#xed;vel a compar&#xea;ncia deste colaborador na data "
				+ "indicada, contacte-nos, por favor, atrav&#xe9;s do telefone 21 350 45 40 "
				+ "ou respondendo ao remetente desta mensagem.</font>"
				+ "</p><p></p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">Cumprimentos,</font>"
				+ "</p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">SIPRP</font>"
//				color=\"#497895\"
				+ "</p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">ATRIUM SALDANHA</font>"
				+ "</p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">Pra&#xe7;a Duque de Saldanha, 1 - 9&#xba;G</font>"
				+ "</p>"
				+ "<p>"
				+ "<font size=\"3\" face=\"Arial\">1050-094 Lisboa"
				+ "</p>" );
		mailDialog.setSize( 1024, 768 );
		mailDialog.setVisible( true );
		System.exit( 0 );
	}
	
	public MailDialog( JFrame owner, String to, String bcc, String subject, String message )
	throws Exception
	{
		super( owner, true );
		this.owner = owner;
		commonStartup();
		setTo( to );
		setBcc( bcc );
		setSubject( subject );
		setMessage( message );
		setModal( true );
		setSize( 1024, 768 );
		setVisible( true );
	}
	
	public MailDialog( JFrame owner )
		throws Exception
	{
		super( owner, true );
		this.owner = owner;
		commonStartup();
		setModal( true );
		setSize( 1024, 768 );
		setVisible( true );
	}
	
	private void commonStartup()
	throws Exception
	{
		setupComponents();
		if( owner != null )
		{
			centerSuper();
		}
		else
		{
			center();
		}
	}
	
	private void setupComponents()
		throws Exception
	{
		setLayout( new BorderLayout() );
		JPanel headerPanel = new JPanel();
		setupHeaderComponents( headerPanel );
		add( headerPanel, BorderLayout.NORTH );
		JPanel htmlPanel = new JPanel();
		setupHTMLComponents( htmlPanel );
		add( htmlPanel, BorderLayout.CENTER );
	}
	
	private void setupHeaderComponents( JPanel headerPanel )
		throws Exception
	{
		Action sendAction = new AbstractAction( "send" ){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public void actionPerformed( ActionEvent e )
			{
				send();
				close();
			}
		};
		sendAction.putValue( Action.SHORT_DESCRIPTION, "Enviar" );
		JButton sendButton = createButton( sendAction, "siprp/medicina/processo/mail/icons/mail2.png" );
		Action attachAction = new AbstractAction( "attach" ){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public void actionPerformed( ActionEvent e )
			{
				FileDialog fd = new FileDialog( owner, "Escolha um ficheiro", FileDialog.LOAD );
				fd.setDirectory( System.getProperty( "user.home" ) );
				fd.setVisible( true );
				//String filename = "c:\\test.xls";
				String filename = fd.getFile();
				if( filename != null )
				{
					String dir = fd.getDirectory();
					String full = filename + " (" + dir + ")";
					Vector values = attachmentsModel.getValues();
					values.add( full );
					attachmentsModel.setValues( values );
				}
			}
		};
		attachAction.putValue( Action.SHORT_DESCRIPTION, "Acrescentar anexo" );
		JButton attachButton = createButton( attachAction, "siprp/medicina/processo/mail/icons/mail_attachment.png" );
		removeAttachmentAction = new AbstractAction( "remove-attachment" ){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public void actionPerformed( ActionEvent e )
			{
				int selected = attachmentsTable.getSelectedRow();
				if( selected > -1 && selected < attachmentsTable.getRowCount() )
				{
					attachmentsModel.removeRowAt( selected );
				}
			}
		};
		removeAttachmentAction.putValue( Action.SHORT_DESCRIPTION, "Remover anexo" );
		JButton removeAttachmentButton = createButton( removeAttachmentAction, "siprp/medicina/processo/mail/icons/delete2.png" );
		removeAttachmentAction.setEnabled( false );
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout( new GridLayout( 1, 2 ) );
		JPanel leftButtonPanel = new JPanel();
		buttonPanel.add( leftButtonPanel );
		JPanel rightButtonPanel = new JPanel();
//		buttonPanel.add( rightButtonPanel );
		leftButtonPanel.setLayout( new FlowLayout( FlowLayout.LEFT ) );
		leftButtonPanel.add( sendButton );
		rightButtonPanel.setLayout( new FlowLayout( FlowLayout.RIGHT ) );
		rightButtonPanel.add( attachButton );
		rightButtonPanel.add( removeAttachmentButton );
		
		JLabel toLabel = new JLabel( "Para:" );
		toText = new JTextField();
		toText.setEditable( false );
		JLabel bccLabel = new JLabel( "C\u00f3pia:" );
		bccText = new JTextField();
		bccText.setEditable( false );
		JLabel assuntoLabel = new JLabel( "Assunto:" );
		subjectText = new JTextField();
		attachmentsModel = new VectorTableModel( new String[]{ "" } );
		attachmentsTable = new BaseTable( attachmentsModel );
		JScrollPane attachmentsScroll = new JScrollPane( attachmentsTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
		attachmentsTable.getSelectionModel().addListSelectionListener( new ListSelectionListener(){

			@Override
			public void valueChanged(ListSelectionEvent e)
			{
				removeAttachmentAction.setEnabled( attachmentsTable.getSelectedRow() != -1 );
			}
			
		} );
		
		TableLayout layout = 
			new TableLayout(
				new double[]{ TableLayoutConstraints.MINIMUM, TableLayoutConstraints.FILL },
				new double[]{ TableLayoutConstraints.PREFERRED, TableLayoutConstraints.MINIMUM, TableLayoutConstraints.MINIMUM,
								TableLayoutConstraints.MINIMUM } );
		layout.setHGap( 2 );
		layout.setVGap( 2 );
		
		headerPanel.setLayout( layout );
		headerPanel.add( buttonPanel, new TableLayoutConstraints( 0, 0, 1, 0 ) );
		headerPanel.add( toLabel, new TableLayoutConstraints( 0, 1 ) );
		headerPanel.add( toText, new TableLayoutConstraints( 1, 1 ) );
//		headerPanel.add( attachmentsScroll, new TableLayoutConstraints( 2, 1, 2, 3 ) );
		headerPanel.add( bccLabel, new TableLayoutConstraints( 0, 2 ) );
		headerPanel.add( bccText, new TableLayoutConstraints( 1, 2 ) );
		headerPanel.add( assuntoLabel, new TableLayoutConstraints( 0, 3 ) );
		headerPanel.add( subjectText, new TableLayoutConstraints( 1, 3 ) );
	}
	
	private void setupHTMLComponents( JPanel htmlPanel )
		throws Exception
	{
		HTMLEditorKit kit = new HTMLEditorKit();
		Action actions[] = kit.getActions();
		Vector<StyledEditorKit.FontSizeAction> fontSizeActions = 
			new Vector<StyledEditorKit.FontSizeAction>();
		for( int n = 0; n <  actions.length; n++ )
		{
			String str = actions[ n ].getValue( Action.NAME ).toString();
			if( str.toLowerCase().indexOf( "font-size" ) != -1 )
			{
				int size = Integer.parseInt( str.split( "-" )[ 2 ] );
				if( size == 16 )
				{
					continue;
				}
				fontSizeActions.add( ( StyledEditorKit.FontSizeAction ) actions[ n ] );
			}
		}
		
		FONT_SIZE_ACTIONS = fontSizeActions.toArray( new StyledEditorKit.FontSizeAction[ fontSizeActions.size() ] );
		Arrays.sort( FONT_SIZE_ACTIONS, new Comparator<StyledEditorKit.FontSizeAction>(){
			public int compare( StyledEditorKit.FontSizeAction fsa1, StyledEditorKit.FontSizeAction fsa2 )
			{
				String str1 = fsa1.getValue( Action.NAME ).toString();
				String str2 = fsa2.getValue( Action.NAME ).toString();
				int size1 = Integer.parseInt( str1.split( "-" )[ 2 ] );
				int size2 = Integer.parseInt( str2.split( "-" )[ 2 ] );
				return size1 > size2 ? 1 : -1;
			}
		} );
		FONT_SIZES = new int[ FONT_SIZE_ACTIONS.length ];
		for( int n = 0; n < FONT_SIZES.length; n++ )
		{
			FONT_SIZES[ n ] = Integer.parseInt( FONT_SIZE_ACTIONS[ n ].getValue( Action.NAME ).toString().split( "-" )[ 2 ] );
		}
		
		bodyPane = new JTextPane();
		bodyPane.setEditorKit( kit );
		ActionMap actionMap = bodyPane.getActionMap();
		
		Action cutAction = actionMap.get( DefaultEditorKit.cutAction );
		cutAction.putValue( Action.SHORT_DESCRIPTION, "Cortar" );
		Action copyAction = actionMap.get( DefaultEditorKit.copyAction );
		copyAction.putValue( Action.SHORT_DESCRIPTION, "Copiar" );
		Action pasteAction = actionMap.get( DefaultEditorKit.pasteAction );
		pasteAction.putValue( Action.SHORT_DESCRIPTION, "Colar" );
		
		Action boldAction = actionMap.get( "font-bold" );
		boldAction.putValue( Action.SHORT_DESCRIPTION, "Bold" );
		Action italicAction = actionMap.get( "font-italic" );
		italicAction.putValue( Action.SHORT_DESCRIPTION, "It\u00e1lico" );
		Action underlineAction = actionMap.get( "font-underline" );
		underlineAction.putValue( Action.SHORT_DESCRIPTION, "Sublinhado" );
		Action fontBiggerAction = new StyledEditorKit.FontSizeAction( "font-bigger", 30 ){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public void actionPerformed( ActionEvent e )
			{
				
				int start = bodyPane.getSelectionStart();
				AttributeSet set = bodyPane.getStyledDocument().getCharacterElement( start ).getAttributes();
				int size = StyleConstants.getFontSize( set );
				for( int n = 0; n < FONT_SIZES.length; n++ )
				{
					if( size < FONT_SIZES[ n ] )
					{
						FONT_SIZE_ACTIONS[ n ].actionPerformed( e );
						break;
					}
				}
				bodyPane.requestFocusInWindow();
			}
		}; 
		fontBiggerAction.putValue( Action.SHORT_DESCRIPTION, "Fonte maior" );
		Action fontSmallerAction = 
			new StyledEditorKit.FontSizeAction( "font-smaller", 5 ){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public void actionPerformed( ActionEvent e )
			{
				
				int start = bodyPane.getSelectionStart();
				AttributeSet set = bodyPane.getStyledDocument().getCharacterElement( start ).getAttributes();
				int size = StyleConstants.getFontSize( set );
				for( int n = FONT_SIZES.length - 1; n >= 0; n-- )
				{
					if( size > FONT_SIZES[ n ] )
					{
						FONT_SIZE_ACTIONS[ n ].actionPerformed( e );
						break;
					}
				}
				bodyPane.requestFocusInWindow();
			}
		};
		fontSmallerAction.putValue( Action.SHORT_DESCRIPTION, "Fonte menor" );
		Action colorAction = 
			new StyledEditorKit.ForegroundAction( "color", Color.black ){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			public void actionPerformed( ActionEvent e )
			{
				ColorChooserDialog dialog = new ColorChooserDialog( owner, Color.black );
				dialog.setVisible( true );
				Color color = dialog.getColor();
				if( color != null )
				{
					bodyPane.requestFocusInWindow();
					Action colorTempAction = new StyledEditorKit.ForegroundAction( "color-temp", color );
					bodyPane.getActionMap().put( "color-temp", colorTempAction );
					colorTempAction.actionPerformed( e );
				}
				bodyPane.requestFocusInWindow();
			}
		};
		colorAction.putValue( Action.SHORT_DESCRIPTION, "C\u00f4r" );
		String fontFamilies[] = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
		JComboBox fontCombo = new JComboBox();
		for( int n = 0; n < fontFamilies.length; n++ )
		{
			fontCombo.addItem( fontFamilies[ n ] );
		}
		fontCombo.addItemListener( new ItemListener(){

			@Override
			public void itemStateChanged(ItemEvent e)
			{
				String selected = ( String ) e.getItem();
				Action fontFamilyAction = 
					new StyledEditorKit.FontFamilyAction( "font-family-action" , selected );
				bodyPane.getActionMap().put( "font-family-action", fontFamilyAction );
				fontFamilyAction.actionPerformed( 
						new ActionEvent( e.getSource(), e.getID(), "" ) );
				bodyPane.requestFocusInWindow();
			}
		} );
		
		Action alignLeftAction = actionMap.get( "left-justify" );
		alignLeftAction.putValue( Action.SHORT_DESCRIPTION, "Alinhado \u00e0 esquerda" );
		Action alignCenterAction = actionMap.get( "center-justify" );
		alignCenterAction.putValue( Action.SHORT_DESCRIPTION, "Centrado" );
		Action alignRightAction = actionMap.get( "right-justify" );
		alignRightAction.putValue( Action.SHORT_DESCRIPTION, "Alinhado \u00e0 direita" );
		Action alignJustifyAction = 
			new StyledEditorKit.AlignmentAction( "justify", 
					javax.swing.text.StyleConstants.ALIGN_JUSTIFIED );
		actionMap.put( "justify", alignJustifyAction );
		alignJustifyAction.putValue( Action.SHORT_DESCRIPTION, "Justificado" );
		
		JButton exportButton = new JButton( "X" );
		exportButton.addActionListener( new ActionListener(){
			public void actionPerformed( ActionEvent e )
			{
				System.out.println( bodyPane.getText() );
			}
		} );
		
		JPanel upperPanel = new JPanel();
		upperPanel.setLayout( new FlowLayout( FlowLayout.LEFT ) );
		upperPanel.add( exportButton );
		upperPanel.add( createButton( cutAction, "siprp/medicina/processo/mail/icons/cut.png" ) );
		upperPanel.add( createButton( copyAction, "siprp/medicina/processo/mail/icons/copy.png" ) );
		upperPanel.add( createButton( pasteAction, "siprp/medicina/processo/mail/icons/paste.png" ) );
		upperPanel.add( new JLabel( " " ) );
		upperPanel.add( createButton( boldAction, "siprp/medicina/processo/mail/icons/text_bold.png" ) );
		upperPanel.add( createButton( italicAction, "siprp/medicina/processo/mail/icons/text_italics.png" ) );
		upperPanel.add( createButton( underlineAction, "siprp/medicina/processo/mail/icons/text_underlined.png" ) );
		upperPanel.add( createButton( fontBiggerAction, "siprp/medicina/processo/mail/icons/font_bigger.png" ) );
		upperPanel.add( createButton( fontSmallerAction, "siprp/medicina/processo/mail/icons/font_smaller.png" ) );
		upperPanel.add( createButton( colorAction, "siprp/medicina/processo/mail/icons/colorwheel.png" ) );
		upperPanel.add( fontCombo );
		upperPanel.add( new JLabel( " " ) );
		upperPanel.add( createButton( alignLeftAction, "siprp/medicina/processo/mail/icons/text_align_left.png" ) );
		upperPanel.add( createButton( alignCenterAction, "siprp/medicina/processo/mail/icons/text_align_center.png" ) );
		upperPanel.add( createButton( alignRightAction, "siprp/medicina/processo/mail/icons/text_align_right.png" ) );
		upperPanel.add( createButton( alignJustifyAction, "siprp/medicina/processo/mail/icons/text_align_justified.png" ) );
		
		htmlPanel.setLayout( new BorderLayout() );
		
		htmlPanel.add( upperPanel, BorderLayout.NORTH );
		htmlPanel.add( new JScrollPane( bodyPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
										JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ), BorderLayout.CENTER );
	}
	
	private JButton createButton( Action action, String iconPath )
		throws Exception
	{
		action.putValue( Action.SMALL_ICON,
				ImageIconLoader.loadImageIcon( getClass(), iconPath ) );
		JButton button = new JButton( action );
		button.setText( null );
		
		return button;
	}
	
	public void setTo( String to )
	{
		toText.setText( to );
	}
	
	public String getTo()
	{
		return toText.getText();
	}
	
	public void setBcc( String bcc )
	{
		bccText.setText( bcc );
	}
	
	public String getBcc()
	{
		return bccText.getText();
	}
	
	public void setSubject( String subject )
	{
		subjectText.setText( subject );
	}
	
	public String getSubject()
	{
		return subjectText.getText();
	}
	
	public void setMessage( String message )
	{
		bodyPane.setText( message );
	}
	
	public String getMessage()
	{
		return bodyPane.getText();
	}
	
	public void send()
	{
//		close();
		String to = toText.getText();
		String bcc = bccText.getText();
		String subject = subjectText.getText();
		String body = bodyPane.getText();
		String attachmentList[] = new String[ attachmentsTable.getRowCount() ];
		byte attachments[][] = new byte[ attachmentsTable.getRowCount() ][];
		Vector values = attachmentsModel.getValues();
		for( int n = 0; n < attachmentList.length; n++ )
		{
			String str = ( String ) values.elementAt( n );
			String name = str.substring( 0, str.indexOf( "(") - 1 );
			String path = str.substring( str.indexOf( "(") + 1, str.indexOf( ")") );
			try
			{
				FileInputStream fis = new FileInputStream( path + name );
				Vector<byte[]> bytes = new Vector<byte[]>();
				int available = 0;
				int total = 0;
				while( ( available = fis.available() ) > 0 )
				{
					byte b[] = new byte[ available ];
					fis.read( b );
					bytes.add( b );
					total += available;
				}
				attachments[ n ] = new byte[ total ];
				int pos = 0;
				for( byte[] chunk : bytes )
				{
					System.arraycopy( chunk, 0, attachments[ n ], pos, chunk.length );
					pos += chunk.length;
				}
			}
			catch( FileNotFoundException fnfex )
			{
				JOptionPane.showMessageDialog( owner, 
						"O ficheiro " + path + name + " n\u00e3o existe.",
						"Ficheiro inexistente",
						JOptionPane.ERROR_MESSAGE );
				return;
			}
			catch( IOException ioex )
			{
				DialogException.showExceptionMessage( ioex, "Erro a ler ficheiro " + path + name, true );
				return;
			}
		}
		MailSender sender = new MailSender();
		try
		{
			sender.send( to, bcc, subject, body, attachmentList, attachments );
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}
	}
	
	public void close()
	{
		SwingUtilities.invokeLater( new Runnable(){
			public void run()
			{
				setVisible( false );
				dispose();
			}
		} );
		
	}
}
