/*
 * WebUpdater.java
 *
 * Created on 27 de Outubro de 2004, 15:54
 */

package siprp.web;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.sql.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

//import siprp.*;
//import siprp.clientes.*;

/**
 *
 * @author  fpalma
 */
public class WebUpdater extends JFrame
	implements ActionListener, Runnable, DocumentListener
{
	private Connection softwareConnection;
	private Connection webConnection;
	
	public static final String GET_ULTIMA_ACTUALIZACAO = "SELECT stamp FROM actualizacao";
	
	public static final String GET_EMPRESAS = 
			"SELECT id, designacao_social, perfil_1, perfil_2, codigo_1, codigo_2, "
			+ "codigo_3, cae, contribuinte, seguranca_social, actividade, servicos, morada, "
			+ "localidade, codigo_postal, distrito, concelho, inactivo, contacto_1 "
			+ "FROM empresas WHERE actualizacao >= ";
	
	public static final String GET_EMAIL = 
			"SELECT email FROM contactos WHERE id = ";
	
	public static final String GET_ESTABELECIMENTOS =
			"SELECT id, empresa_id, nome, contacto, morada, localidade, codigo_postal, inactivo "
			+ "FROM estabelecimentos WHERE actualizacao >= ";
	
	public static final String GET_TRABALHADORES =
			"SELECT id, nome, sexo, data_nascimento, numero_mecanografico, categoria, estabelecimento_id, data_demissao, inactivo "
			+ "FROM trabalhadores WHERE actualizacao >= ";
	
	public static final String GET_CONTACTO =
			"SELECT nome, telefone, telemovel, fax, email, cargo FROM contactos WHERE id = ";
	
	public static final String GET_MARCACOES_ESTABELECIMENTO =
			"SELECT id, data, realizada, data_relatorio FROM marcacoes_estabelecimento "
			+ "WHERE estabelecimento_id = ";
	
	public static final String GET_EXAMES_TRABALHADOR =
			"SELECT id, data, realizada, data_relatorio FROM marcacoes_trabalhador "
			+ "WHERE tipo = 0 and trabalhador_id = ?trabalhador_id "
			+ "ORDER BY data";
	
	public static final String GET_CONSULTAS_TRABALHADOR =
			"SELECT id, data, realizada, data_relatorio FROM marcacoes_trabalhador "
			+ "WHERE tipo = 1 and trabalhador_id = ?trabalhador_id "
			+ "ORDER BY data";
	
	public static final String GET_ID_FICHA_APTIDAO = 
		"SELECT MAX(id) FROM exames WHERE trabalhador_id = ?trabalhador_id AND inactivo <> 'y'";
	
	public static final String GET_DADOS_FICHA_APTIDAO = 
			"SELECT data, resultado FROM exames WHERE id = ?id";
	
	public static final String DELETE_TRABALHADOR =
			"DELETE FROM trabalhadores WHERE id = ";
	
	public static final String DELETE_TRABALHADORES_BY_ESTABELECIMENTO =
			"DELETE FROM trabalhadores WHERE estabelecimento_id = ";
	
	public static final String DELETE_ESTABELECIMENTO =
			"DELETE FROM estabelecimentos WHERE id = ";
	
	public static final String DELETE_ESTABELECIMENTOS_BY_EMPRESA =
			"DELETE FROM estabelecimentos WHERE empresa_id = ";
	
	public static final String DELETE_TRABALHADORES_BY_EMPRESA =
			"DELETE FROM trabalhadores WHERE estabelecimento_id IN ( SELECT id FROM estabelecimentos WHERE empresa_id = ?empresa_id )";
	
	public static final String DELETE_EMPRESA = 
			"DELETE FROM empresas WHERE id = ";
	
	public static final String CREATE_EMPRESA =
			"INSERT INTO empresas(id) VALUES( ?id )";
	
	public static final String CREATE_ESTABELECIMENTO =
			"INSERT INTO estabelecimentos(id) VALUES( ?id )";
	
	public static final String CREATE_TRABALHADOR =
			"INSERT INTO trabalhadores(id) VALUES( ?id )";
	
	public static final String UPDATE_EMPRESA = 
			"UPDATE empresas SET morada = ?morada, codigo_postal = ?codigo_postal, "
			+ "localidade = ?localidade, distrito = ?distrito, concelho = ?concelho, "
			+ "perfil_1 = ?perfil_1, perfil_2 = ?perfil_2, codigo = ?codigo, cae = ?cae, "
			+ "contribuinte = ?contribuinte, seguranca_social = ?seguranca_social, "
			+ "actividade = ?actividade, servicos = ?servicos, designacao_social = ?designacao_social, "
			+ "email = ?email "
			+ "WHERE id = ?id";
	
	public static final String UPDATE_ESTABELECIMENTO = 
			"UPDATE estabelecimentos SET empresa_id = ?empresa_id, morada = ?morada, "
			+ "codigo_postal = ?codigo_postal, localidade = ?localidade, " 
			+ "ultima_visita = ?ultima_visita, realizada = ?realizada, "
			+ "proxima_visita = ?proxima_visita, nome = ?nome "
			+ "WHERE id = ?id";
	
	public static final String UPDATE_TRABALHADOR = 
			"UPDATE trabalhadores SET sexo = ?sexo, data_nascimento = ?data_nascimento, "
			+ "numero_mecanografico = ?numero_mecanografico, categoria = ?categoria, "        
			+ "ultimo_exame = ?ultimo_exame, realizado = ?realizado, proximo_exame = ?proximo_exame, "
			+ "ultima_consulta = ?ultima_consulta, realizada = ?realizada, "
			+ "proxima_consulta = ?proxima_consulta, nome = ?nome, "
			+ "resultado = ?resultado, data_ficha = ?data_ficha, "
			+ "estabelecimento_id = ?estabelecimento_id "
			+ "WHERE id = ?id";
	
	public static final String UPDATE_ACTUALIZACAO = "UPDATE actualizacao SET stamp = ";
	
	
	public static final String PROPERTIES_FILE = "updtprop.txt";
	public static final String PROP_LOCAL = "interno";
	public static final String PROP_LOCAL_U = "iuser";
	public static final String PROP_LOCAL_P = "ipasswd";
	public static final String PROP_REMOTE = "externo";
	public static final String PROP_REMOTE_U = "euser";
	public static final String PROP_REMOTE_P = "epasswd";
	public static final String PROP_INTERVAL = "intervalo";
	
	
	protected Vector deletes;
	protected Vector updates;
	
	protected Thread updateThread;
	
	protected JTextField servidorInternoText;
	protected JTextField servidorExternoText;
	protected JTextField intervaloText;
	protected JTextField ultimaActualizacaoText;
	protected JTextField proximaActualizacaoText;
	protected JButton actionButton;
	protected JButton saveButton;
	protected JButton cancelButton;
	protected JLabel stateLabel;
	
	protected boolean running;
	protected String servidorInterno;
	protected String servidorExterno;
	protected String internalUser;
	protected String internalPassword;
	protected String externalUser;
	protected String externalPassword;
	protected long intervalo;
	
	/** Creates a new instance of WebUpdater */
	public WebUpdater()
	{
		deletes = new Vector();
		updates = new Vector();
		running = false;
		servidorInterno = "ws_fpalma";
		servidorExterno = "localhost:5436";
		intervalo = 10;
		setupComponents();
	}
	
	protected void setupComponents()
	{
		setSize( 500, 200 );
		setResizable( false );
		setTitle( "Actualiza\u00e7\u00e3o do Site" );
		JLabel servidorInternoLabel = new JLabel( "Servidor Interno" );
		servidorInternoText = new JTextField();
		servidorInternoText.setPreferredSize( new Dimension( 120, 20 ) );
		servidorInternoText.setForeground( Color.red );
		JLabel servidorExternoLabel = new JLabel( "Servidor Externo" );
		servidorExternoText = new JTextField();
		servidorExternoText.setPreferredSize( new Dimension( 120, 20 ) );
		servidorExternoText.setForeground( Color.red );
		JLabel intervaloLabel = new JLabel( "Intervalo de Actualiza\u00e7\u00e3o (minutos)" );
		intervaloText = new JTextField();
		intervaloText.setPreferredSize( new Dimension( 50, 20 ) );
		JLabel ultimaActualizacaoLabel = new JLabel( "\u00daltima Actualiza\u00e7\u00e3o" );
		ultimaActualizacaoText = new JTextField();
		ultimaActualizacaoText.setPreferredSize( new Dimension( 120, 20 ) );
		ultimaActualizacaoText.setEditable( false );
		JLabel proximaActualizacaoLabel = new JLabel( "Pr\u00f3xima Actualiza\u00e7\u00e3o" );
		proximaActualizacaoText = new JTextField();
		proximaActualizacaoText.setPreferredSize( new Dimension( 120, 20 ) );
		proximaActualizacaoText.setEditable( false );
		actionButton = new JButton( "Executar" );
		saveButton = new JButton( "Guardar Altera\u00e7\u00f5es" );
		saveButton.setEnabled( false );
		cancelButton = new JButton( "Cancelar Altera\u00e7\u00f5es" );
		cancelButton.setEnabled( false );
		stateLabel = new JLabel( " " );
		JPanel buttonPanel = new JPanel();
		JPanel pad = new JPanel();
		pad.setPreferredSize( new Dimension( 120, 20 ) );
		
		Container container = getContentPane();
		GridBagLayout gridbag = new GridBagLayout();
		container.setLayout( gridbag );
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = new Insets( 1, 1, 1, 1 );
//		constraints.anchor = GridBagConstraints.EAST;
		constraints.fill = GridBagConstraints.BOTH;
		constraints.weighty = 0;
		constraints.gridheight = 1;
		
		constraints.weightx = 0;
		constraints.gridwidth = 1;
		gridbag.setConstraints( servidorInternoLabel, constraints );
		gridbag.setConstraints( servidorExternoLabel, constraints );
		gridbag.setConstraints( intervaloLabel, constraints );
		gridbag.setConstraints( ultimaActualizacaoLabel, constraints );
		gridbag.setConstraints( proximaActualizacaoLabel, constraints );
		
		constraints.weightx = 1;
		constraints.gridwidth = GridBagConstraints.REMAINDER;
		gridbag.setConstraints( servidorInternoText, constraints );
		gridbag.setConstraints( servidorExternoText, constraints );
		gridbag.setConstraints( ultimaActualizacaoText, constraints );
		gridbag.setConstraints( proximaActualizacaoText, constraints );
		gridbag.setConstraints( buttonPanel, constraints );
		gridbag.setConstraints( stateLabel, constraints );
		
		constraints.weightx = 0.5;
		constraints.gridwidth = 1;
		gridbag.setConstraints( intervaloText, constraints );
		
		constraints.weightx = 0.5;
		constraints.gridwidth = GridBagConstraints.REMAINDER;
		gridbag.setConstraints( pad, constraints );
		
		container.add( servidorInternoLabel );
		container.add( servidorInternoText );
		container.add( servidorExternoLabel );
		container.add( servidorExternoText );
		container.add( intervaloLabel );
		container.add( intervaloText );
		container.add( pad );
		container.add( ultimaActualizacaoLabel );
		container.add( ultimaActualizacaoText );
		container.add( proximaActualizacaoLabel );
		container.add( proximaActualizacaoText );
		container.add( buttonPanel );
		container.add( stateLabel );
		
		buttonPanel.setLayout( new FlowLayout( FlowLayout.RIGHT ) );
		buttonPanel.add( saveButton );
		buttonPanel.add( cancelButton );
		buttonPanel.add( actionButton );
		
		actionButton.addActionListener( this );
		stateLabel.setText( "Parado" );
		stateLabel.setForeground( Color.red );
		
//		servidorInternoText.setText( servidorInterno );
//		servidorExternoText.setText( servidorExterno );
//		intervaloText.setText( "" + intervalo );
		reload();
		
		servidorInternoText.getDocument().addDocumentListener( this );
		servidorExternoText.getDocument().addDocumentListener( this );
		intervaloText.getDocument().addDocumentListener( this );
		saveButton.addActionListener( this );
		cancelButton.addActionListener( this );
	}
		
	public void actionPerformed(java.awt.event.ActionEvent actionEvent)
	{
		Object source = actionEvent.getSource();
		if( actionButton.equals( source ) )
		{
			if( running )
			{
				running = false;
				updateThread.interrupt();
				actionButton.setText( "Executar" );
				stateLabel.setText( "Parado" );
				stateLabel.setBackground( Color.red );
			}
			else
			{
				updateThread = new Thread( this );
				updateThread.start();
				actionButton.setText( "Parar" );
			}
		}
		else if( saveButton.equals( source ) )
		{
			save();
			saveButton.setEnabled( false );
			cancelButton.setEnabled( false );
		}
		else if( cancelButton.equals( source ) )
		{
			reload();
			saveButton.setEnabled( false );
			cancelButton.setEnabled( false );
		}
	}
	
		
	public void changedUpdate(javax.swing.event.DocumentEvent documentEvent)
	{
		saveButton.setEnabled( true );
		cancelButton.setEnabled( true );
	}	

	public void insertUpdate(javax.swing.event.DocumentEvent documentEvent)
	{
		saveButton.setEnabled( true );
		cancelButton.setEnabled( true );
	}	
	
	public void removeUpdate(javax.swing.event.DocumentEvent documentEvent)
	{
		saveButton.setEnabled( true );
		cancelButton.setEnabled( true );
	}
	
	protected void save()
	{
		Properties props = new Properties();
		try
		{
			OutputStream out = new FileOutputStream( PROPERTIES_FILE );
			String auxSI = servidorInternoText.getText();
			String auxSE = servidorExternoText.getText();
			String auxI = intervaloText.getText();;
			if( auxSI == null || auxSI.length() == 0 ||
				auxSE == null || auxSE.length() == 0 ||
				auxI == null || auxI.length() == 0 )
			{
				throw new Exception( "" );
			}
			intervalo = Long.parseLong( auxI );
			servidorInterno = auxSI;
			servidorExterno = auxSE;
			props.setProperty( PROP_LOCAL, servidorInterno );
			props.setProperty( PROP_LOCAL_U, internalUser );
			props.setProperty( PROP_LOCAL_P, internalPassword );
			props.setProperty( PROP_REMOTE, servidorExterno );
			props.setProperty( PROP_REMOTE_U, externalUser );
			props.setProperty( PROP_REMOTE_P, externalPassword );
			props.setProperty( PROP_INTERVAL, "" + intervalo );
			props.store( out, "Configura\u00e7\u00e3o da Ferramenta de Actualiza\u00e7\u00e3o da SIPRP" );
			out.close();
		}
		catch( Exception ex )
		{
			JOptionPane.showMessageDialog( this, "Erro a gravar altera\u00e7\u00f5es", "Erro",
				JOptionPane.ERROR_MESSAGE );
		}
	}
	
	protected void reload()
	{
		Properties props = new Properties();
		try
		{
			
System.out.println( new File( PROPERTIES_FILE ) );
			InputStream in = new FileInputStream( PROPERTIES_FILE );
			props.load( in );
			internalUser = props.getProperty( PROP_LOCAL_U );
			internalPassword = props.getProperty( PROP_LOCAL_P );
			externalUser = props.getProperty( PROP_REMOTE_U );
			externalPassword = props.getProperty( PROP_REMOTE_P );
			
			String aux;
			aux = props.getProperty( PROP_LOCAL );
			if( aux != null && aux.length() > 0 )
			{
				servidorInterno = aux;
			}
			aux = props.getProperty( PROP_REMOTE );
			if( aux != null && aux.length() > 0 )
			{
				servidorExterno = aux;
			}
			aux = props.getProperty( PROP_INTERVAL );
			if( aux != null && aux.length() > 0 )
			{
				try
				{
					intervalo = Long.parseLong( aux );
				}
				catch( NumberFormatException nfe )
				{
				}
			}
			
		}
		catch( Exception ex )
		{
			JOptionPane.showMessageDialog( this, "Erro a carregar os dados", "Erro",
				JOptionPane.ERROR_MESSAGE );
		}
		servidorInternoText.setText( servidorInterno );
		servidorExternoText.setText( servidorExterno );
		intervaloText.setText( "" + intervalo );
	}
	
	public void run()
	{
		running = true;
		while( true )
		{
			boolean erro = false;
			if( !running )
			{
				return;
			}
			proximaActualizacaoText.setText( "" );
			try
			{
				stateLabel.setText( "A Actualizar" );
				stateLabel.setForeground( Color.green );
				doUpdates();
				java.util.Date date = new java.util.Date();
				ultimaActualizacaoText.setText( date.toString() );
			}
			catch( Exception ex )
			{
				erro = true;
				stateLabel.setText( "ERRO A ACTUALIZAR!!!" );
				stateLabel.setForeground( Color.red );
			}
			if( !running )
			{
				return;
			}
			try
			{
				if( !erro )
				{
					stateLabel.setText( "Em Intervalo (" + intervalo + " minuto" + ( intervalo > 1 ? "s" : "" ) + ")" );
					stateLabel.setForeground( Color.black );
				}
				Calendar cal = Calendar.getInstance();
				cal.add( Calendar.MINUTE, (int)intervalo );
				proximaActualizacaoText.setText( "" + cal.getTime() );
				Thread.sleep( intervalo * 60000 );
			}
			catch( InterruptedException iex )
			{
			}
		}
	}	
		
	protected void doUpdates()
		throws Exception
	{
		try
		{
			connect();
			getData();
			updateData();
		}
		catch( Exception ex ) 
		{
			ex.printStackTrace();
			throw ex;
		}
		
	}
	
	/**
	 * @param args the command line arguments
	 */
	public static void main( String[] args )
		throws Exception
	{
		WebUpdater updater = new WebUpdater();
		updater.show();
	}
	
	protected void connect()
		throws Exception
	{
		Class.forName( "org.postgresql.Driver" );
		Class.forName( "com.mysql.jdbc.Driver" );
		webConnection = DriverManager.getConnection( "jdbc:postgresql://" + servidorExterno + "/siprp", externalUser, externalPassword );
		webConnection.setAutoCommit( true );
		softwareConnection = DriverManager.getConnection( "jdbc:mysql://" + servidorInterno + "/siprp", internalUser, internalPassword );
//		softwareConnection = DriverManager.getConnection( "jdbc:postgresql://" + servidorInterno + "/siprp", internalUser, internalPassword );
		softwareConnection.setAutoCommit( true );
	}
	
	protected void getData()
		throws Exception
	{
		Object r[][];
		r = doQuery( webConnection, GET_ULTIMA_ACTUALIZACAO );
		String actualizacao = "'" + r[0][0] + "'";
		Calendar cal = Calendar.getInstance();
		//int hour = cal.get( Calendar.HOUR_OF_DAY );
		//if( hour < 3 && hour > 1 )
		//{	
		//	actualizacao = "'1970-01-01 00:00:00'";
		//}
		doQuery(softwareConnection, "DELETE FROM actualizacao;", true);
		doQuery(softwareConnection, "INSERT INTO actualizacao(hora) VALUES(now());", true);
		readTrabalhadores( actualizacao );
		readEstabelecimentos( actualizacao );
		readEmpresas( actualizacao );
	}
	
	protected void updateData()
		throws Exception
	{
		System.out.println( "DELETES" );
		for( int d = 0; d < deletes.size(); d++ )
		{
			try
			{
				System.out.println( deletes.elementAt( d ).toString() );
				doQuery( webConnection, deletes.elementAt( d ).toString(), true );
			}
			catch( Exception ex )
			{
				ex.printStackTrace();
			}
		}
		System.out.println( "" );
		System.out.println( "UPDATES" );
		for( int u = 0; u < updates.size(); u++ )
		{
			String queries[] = ( String[] ) updates.elementAt( u );
			System.out.println( queries[ 0 ] + "\n " + queries[ 1 ] );
			try
			{
				doQuery( webConnection, queries[ 0 ], true );
			}
			catch( Exception ex )
			{
				System.out.println( "                            ERRO DE INSERT" );
			}
			try
			{
				doQuery( webConnection, queries[ 1 ], true );
			}
			catch( Exception ex )
			{
				ex.printStackTrace();
			}	
		}
		Object r[][] = doQuery( softwareConnection, "SELECT hora FROM actualizacao;" );
		String actualizacao = "'" + r[0][0] + "'";
		doQuery( webConnection, UPDATE_ACTUALIZACAO + actualizacao, true );
	}
	
	protected void readTrabalhadores( String actualizacao )
		throws Exception
	{
		Object trabalhadores[][] = doQuery( softwareConnection, GET_TRABALHADORES + actualizacao );
		for( int t = 0; t < trabalhadores.length; t++ )
		{
			for( int c = 0; c < trabalhadores[ t ].length; c++ )
			{
				if( trabalhadores[ t ][ c ] instanceof String )
				{
					trabalhadores[ t ][ c ] = unicodeToHTML( (String) trabalhadores[ t ][ c ] );
				}
			}
			int id = ( ( Number ) trabalhadores[t][0] ).intValue();
			boolean inactivo = "y".equals( trabalhadores[ t ][ trabalhadores[ t ].length - 1 ] ) || 
								trabalhadores[ t ][ trabalhadores[ t ].length - 2 ] != null;
			if( inactivo )
			{
				deletes.add( DELETE_TRABALHADOR + id );
				continue;
			}
			String queries[] = new String[ 2 ];
			updates.insertElementAt( queries, 0 );
			queries[ 0 ] = CREATE_TRABALHADOR.replaceFirst( "[?]id", "" + id );
			String update = UPDATE_TRABALHADOR.replaceFirst( "[?]id", "" + id );
			
			String nome = "'" + trabalhadores[ t ][ 1 ] + "'";
			update = update.replaceFirst( "[?]nome", nome );
			String sexo = "'" + trabalhadores[ t ][ 2 ] + "'";
			update = update.replaceFirst( "[?]sexo", sexo );
			String dataNasc;
			if( trabalhadores[ t ][ 3 ] != null )
			{
				dataNasc = "'" + trabalhadores[ t ][ 3 ] + "'";
			}
			else
			{
				dataNasc = "''";
			}
			update = update.replaceFirst( "[?]data_nascimento", dataNasc );
			String numeroMecanografico;
			if( trabalhadores[ t ][ 4 ] != null )
			{
				numeroMecanografico = "'" + trabalhadores[ t ][ 4 ] + "'";
			}
			else
			{
				numeroMecanografico = "''";
			}
			update = update.replaceFirst( "[?]numero_mecanografico", numeroMecanografico );
			String categoria;
			if( trabalhadores[ t ][ 5 ] != null )
			{
				categoria = "'" + trabalhadores[ t ][ 5 ] + "'";
			}
			else
			{
				categoria = "''";
			}
			update = update.replaceFirst( "[?]categoria", categoria );
			int estabelecimentoID = ( ( Number ) trabalhadores[t][6] ).intValue();
			update = update.replaceFirst( "[?]estabelecimento_id", "" + estabelecimentoID );
			Object exames[][] = doQuery( softwareConnection, 
										GET_EXAMES_TRABALHADOR.replaceFirst( "[?]trabalhador_id", ""+id ) );
			
			if( exames != null && exames.length > 0 )
			{
				java.util.Date dataExame2 = ( java.util.Date ) exames[ exames.length - 1 ] [ 1 ];
				String realizado2 = ( String ) exames[ exames.length - 1 ][ 2 ];
				java.util.Date dataExame1;
				String realizado1;
				if( exames.length >= 2 )
				{
					dataExame1 = ( java.util.Date ) exames[ exames.length - 2 ] [ 1 ];
					realizado1 = ( String ) exames[ exames.length - 2 ][ 2 ];
				}
				else
				{
					dataExame1 = dataExame2;
					realizado1 = realizado2;
				}
				if( "y".equals( realizado2 ) )
				{
					update = update.replaceFirst( "[?]ultimo_exame", "'" + dataExame2 + "'" );
					update = update.replaceFirst( "[?]realizado", "'" + realizado2 + "'" );
					update = update.replaceFirst( "[?]proximo_exame", "null" );
				}
				else if( new java.util.Date().after( dataExame2 ) )
				{
					update = update.replaceFirst( "[?]ultimo_exame", "'" + dataExame2 + "'" );
					update = update.replaceFirst( "[?]realizado", "'" + realizado2 + "'" );
					update = update.replaceFirst( "[?]proximo_exame", "null" );
				}
				else
				{
					update = update.replaceFirst( "[?]proximo_exame", "'" + dataExame2 + "'" );
					if( !dataExame2.equals( dataExame1 ) )
					{
						update = update.replaceFirst( "[?]ultimo_exame", "'" + dataExame1 + "'" ); 
						update = update.replaceFirst( "[?]realizado", "'" + realizado1 + "'" );
					}
					else
					{
						update = update.replaceFirst( "[?]ultimo_exame", "null" );
						update = update.replaceFirst( "[?]realizado", "null" );
					}
				}
			}
			else
			{
				update = update.replaceFirst( "[?]ultimo_exame", "null" );
				update = update.replaceFirst( "[?]realizado", "null" );
				update = update.replaceFirst( "[?]proximo_exame", "null" );
			}
			Object consultas[][] = doQuery( softwareConnection, 
										GET_CONSULTAS_TRABALHADOR.replaceFirst( "[?]trabalhador_id", ""+id ) );
			
			if( consultas != null && consultas.length > 0 )
			{
				java.util.Date dataConsulta2 = ( java.util.Date ) consultas[ consultas.length - 1 ] [ 1 ];
				String realizada2 = ( String ) consultas[ consultas.length - 1 ][ 2 ];
				java.util.Date dataConsulta1;
				java.util.Date dataRelatorio1;
				java.util.Date dataRelatorio2 = (java.util.Date) consultas[ consultas.length - 1 ][ 3 ];
				String realizada1;
				if( consultas.length >= 2 )
				{
					dataConsulta1 = ( java.util.Date ) consultas[ consultas.length - 2 ] [ 1 ];
					realizada1 = ( String ) consultas[ consultas.length - 2 ][ 2 ];
					dataRelatorio1 = (java.util.Date) consultas[ consultas.length - 2 ][ 3 ];
				}
				else
				{
					dataConsulta1 = dataConsulta2;
					realizada1 = realizada2;
					dataRelatorio1 = dataRelatorio2;
				}
				if( "y".equals( realizada2 ) )
				{
					update = update.replaceFirst( "[?]ultima_consulta", "'" + dataConsulta2 + "'" ); 
					update = update.replaceFirst( "[?]realizada", "'" + realizada2 + "'" );
					update = update.replaceFirst( "[?]proxima_consulta", "null" );
					if( dataRelatorio2 != null )
					{
						update = update.replaceFirst( "[?]data_ficha", "'" + dataRelatorio2 + "'" );
					}
					else
					{
						update = update.replaceFirst( "[?]data_ficha", "null" );
					}
				}
				else if( new java.util.Date().after( dataConsulta2 ) )  
				{
					update = update.replaceFirst( "[?]ultima_consulta", "'" + dataConsulta2 + "'" );
					update = update.replaceFirst( "[?]realizada", "'" + realizada2 + "'" );
					update = update.replaceFirst( "[?]proxima_consulta", "null" );
					if( dataRelatorio2 != null )
					{
						update = update.replaceFirst( "[?]data_ficha", "'" + dataRelatorio2 + "'" );
					}
					else
					{
						update = update.replaceFirst( "[?]data_ficha", "null" );
					}
				}
				else
				{
					update = update.replaceFirst( "[?]proxima_consulta", "'" + dataConsulta2 + "'" );
					if( !dataConsulta2.equals( dataConsulta1 ) )
					{
						update = update.replaceFirst( "[?]ultima_consulta", "'" + dataConsulta1 + "'" );
						update = update.replaceFirst( "[?]realizada", "'" + realizada1 + "'" );
						if( dataRelatorio1 != null )
						{
							update = update.replaceFirst( "[?]data_ficha", "'" + dataRelatorio1 + "'" );
						}
						else
						{
							update = update.replaceFirst( "[?]data_ficha", "null" );
						}
					}
					else
					{
						update = update.replaceFirst( "[?]ultima_consulta", "null" );
						update = update.replaceFirst( "[?]realizada", "null" );
						update = update.replaceFirst( "[?]data_ficha", "null" );
					}
				}
			}
			else
			{
				update = update.replaceFirst( "[?]ultima_consulta", "null" );
				update = update.replaceFirst( "[?]realizada", "null" );
				update = update.replaceFirst( "[?]proxima_consulta", "null" );
				update = update.replaceFirst( "[?]data_ficha", "null" );
				
			}
			Object fichas[][] = doQuery( softwareConnection, 
										GET_ID_FICHA_APTIDAO.replaceFirst( "[?]trabalhador_id", ""+id ) );
			if( fichas != null && fichas.length > 0 && fichas[0].length > 0 && fichas[0][0] != null )
			{
				Integer idFicha = (Integer)fichas[0][0];
				fichas = doQuery( softwareConnection, 
										GET_DADOS_FICHA_APTIDAO.replaceFirst( "[?]id", "" + idFicha ) );
				java.util.Date dataFicha = ( java.util.Date ) fichas[ 0 ][ 0 ];
				/*if( dataFicha != null )
				{
					update = update.replaceFirst( "[?]data_ficha", "null" );
				}
				else
				{
					update = update.replaceFirst( "[?]data_ficha", "'" + dataFicha + "'" );
				}*/
				Integer resultadoFicha = (Integer) fichas[ 0 ][ 1 ];
				if( resultadoFicha != null )
				{
					switch( resultadoFicha.intValue() )
					{
						case 1:
							update = update.replaceFirst( "[?]resultado", "'Apto'" );
							break;
						case 2:
							update = update.replaceFirst( "[?]resultado", "'Apto Condicionalmente'" );
							break;
						case 3:
							update = update.replaceFirst( "[?]resultado", "'Inapto Temporariamente'" );
							break;
						case 4:
							update = update.replaceFirst( "[?]resultado", "'Inapto Definitivamente'" );
							break;
						default:
							update = update.replaceFirst( "[?]resultado", "null" );
					}
				}
				else
				{
					update = update.replaceFirst( "[?]resultado", "null" );
				}
			}
			else
			{
				update = update.replaceFirst( "[?]data_ficha", "null" );
				update = update.replaceFirst( "[?]resultado", "null" );
			}
			
			queries[ 1 ] = update;
			
		}
	}
	
	protected void readEstabelecimentos( String actualizacao )
		throws Exception
	{
		Object estabelecimentos[][] = doQuery( softwareConnection, GET_ESTABELECIMENTOS + actualizacao );
		//id, empresa_id, nome, contacto, inactivo
		for( int t = 0; t < estabelecimentos.length; t++ )
		{
			for( int c = 0; c < estabelecimentos[ t ].length; c++ )
			{
				if( estabelecimentos[ t ][ c ] instanceof String )
				{
					estabelecimentos[ t ][ c ] = unicodeToHTML( (String) estabelecimentos[ t ][ c ] );
				}
			}
			int id = ( ( Number ) estabelecimentos[t][0] ).intValue();
			boolean inactivo = "y".equals( estabelecimentos[ t ][ estabelecimentos[ t ].length - 1 ] );
			if( inactivo )
			{
				deletes.add( DELETE_TRABALHADORES_BY_ESTABELECIMENTO + id );
				deletes.add( DELETE_ESTABELECIMENTO + id );
				continue;
			}
			String queries[] = new String[ 2 ];
			updates.insertElementAt( queries, 0 );
			queries[ 0 ] = CREATE_ESTABELECIMENTO.replaceFirst( "[?]id", "" + id );
			String update = UPDATE_ESTABELECIMENTO.replaceFirst( "[?]id", "" + id );
			
			int empresaID = ( ( Number ) estabelecimentos[t][1] ).intValue();
			update = update.replaceFirst( "[?]empresa_id", "" + empresaID );
			String nome = "'" + estabelecimentos[ t ][ 2 ] + "'";
			update = update.replaceFirst( "[?]nome", nome );
			String morada;
			if( estabelecimentos[ t ][ 4 ] != null )
			{
				morada = "'" + estabelecimentos[ t ][ 4 ] + "'";
			}
			else
			{
				morada = "''";
			}
			update = update.replaceFirst( "[?]morada", morada );
			String localidade;
			if( estabelecimentos[ t ][ 5 ] != null )
			{
				localidade = "'" + estabelecimentos[ t ][ 5 ] + "'";
			}
			else
			{
				localidade = "''";
			}
			update = update.replaceFirst( "[?]localidade", localidade );
			String codigoPostal;
			if( estabelecimentos[ t ][ 6 ] != null )
			{
				codigoPostal = "'" + estabelecimentos[ t ][ 6 ] + "'";
			}
			else
			{
				codigoPostal = "''";
			}
			update = update.replaceFirst( "[?]codigo_postal", codigoPostal );

			Object marcacoes[][] = doQuery( softwareConnection, 
										GET_MARCACOES_ESTABELECIMENTO +id );
			
			if( marcacoes != null && marcacoes.length > 0 )
			{
				java.util.Date dataConsulta2 = ( java.util.Date ) marcacoes[ marcacoes.length - 1 ] [ 1 ];
				String realizada2 = ( String ) marcacoes[ marcacoes.length - 1 ][ 2 ];
				java.util.Date dataConsulta1;
				String realizada1;
				if( marcacoes.length >= 2 )
				{
					dataConsulta1 = ( java.util.Date ) marcacoes[ marcacoes.length - 2 ] [ 1 ];
					realizada1 = ( String ) marcacoes[ marcacoes.length - 2 ][ 2 ];
				}
				else
				{
					dataConsulta1 = dataConsulta2;
					realizada1 = realizada2;
				}
				if( "y".equals( realizada2 ) )
				{
					update = update.replaceFirst( "[?]ultima_visita", "'" + dataConsulta2 + "'" );
					update = update.replaceFirst( "[?]realizada", "'" + realizada2 + "'" );
					update = update.replaceFirst( "[?]proxima_visita", "null" );
				}
				else if( new java.util.Date().after( dataConsulta2 ) )
				{
					update = update.replaceFirst( "[?]ultima_visita", "'" + dataConsulta2 + "'" );
					update = update.replaceFirst( "[?]realizada", "'" + realizada2 + "'" );
					update = update.replaceFirst( "[?]proxima_visita", "null" );
				}
				else
				{
					update = update.replaceFirst( "[?]proxima_visita", "'" + dataConsulta2 + "'" );
					if( !dataConsulta2.equals( dataConsulta1 ) )
					{
						update = update.replaceFirst( "[?]ultima_visita", "'" + dataConsulta1 + "'" );
						update = update.replaceFirst( "[?]realizada", "'" + realizada2 + "'" );
					}
					else
					{
						update = update.replaceFirst( "[?]ultima_visita", "null" );
						update = update.replaceFirst( "[?]realizada", "null" );
					}
				}
			}
			else
			{
				update = update.replaceFirst( "[?]ultima_visita", "null" );
				update = update.replaceFirst( "[?]realizada", "null" );
				update = update.replaceFirst( "[?]proxima_visita", "null" );
			}
			
			queries[ 1 ] = update;
		}
	}
	
	protected void readEmpresas( String actualizacao )
		throws Exception
	{
		Object empresas[][] = doQuery( softwareConnection, GET_EMPRESAS + actualizacao );
		//id, empresa_id, nome, contacto, inactivo
		for( int t = 0; t < empresas.length; t++ )
		{
			for( int c = 0; c < empresas[ t ].length; c++ )
			{
				if( empresas[ t ][ c ] instanceof String )
				{
					empresas[ t ][ c ] = unicodeToHTML( (String) empresas[ t ][ c ] );
				}
			}
			int id = ( ( Number ) empresas[t][0] ).intValue();
			boolean inactivo = "y".equals( empresas[ t ][ 17 ] );
			if( inactivo )
			{
				String str = DELETE_TRABALHADORES_BY_EMPRESA.replaceFirst( "[?]empresa_id", "" + id );
				deletes.add( str );
				deletes.add( DELETE_ESTABELECIMENTOS_BY_EMPRESA + id );
				deletes.add( DELETE_EMPRESA + id );
				continue;
			}
			String queries[] = new String[ 2 ];
			updates.insertElementAt( queries, 0 );
			queries[ 0 ] = CREATE_EMPRESA.replaceFirst( "[?]id", "" + id );
			String update = UPDATE_EMPRESA.replaceFirst( "[?]id", "" + id );
			
			String designacaoSocial = "'" + empresas[ t ][ 1 ] + "'";
			update = update.replaceFirst( "[?]designacao_social", designacaoSocial );
			String cae;
			if( empresas[ t ][ 7 ] != null )
			{
				cae = "'" + empresas[ t ][ 7 ] + "'";
			}
			else
			{
				cae = "''";
			}
			update = update.replaceFirst( "[?]cae", cae );
			String contribuinte;
			if( empresas[ t ][ 8 ] != null )
			{
				contribuinte = "'" + empresas[ t ][ 8 ] + "'";
			}
			else
			{
				contribuinte = "''";
			}
			update = update.replaceFirst( "[?]contribuinte", contribuinte );
			String segurancaSocial;
			if( empresas[ t ][ 9 ] != null )
			{
				segurancaSocial = "'" + empresas[ t ][ 9 ] + "'";
			}
			else
			{
				segurancaSocial = "''";
			}
			update = update.replaceFirst( "[?]seguranca_social", segurancaSocial );
			String actividade;
			if( empresas[ t ][ 10 ] != null )
			{
				actividade = "'" + empresas[ t ][ 10 ] + "'";
			}
			else
			{
				actividade = "''";
			}
			update = update.replaceFirst( "[?]actividade", actividade );
			String morada;
			if( empresas[ t ][ 12 ] != null )
			{
				morada = "'" + empresas[ t ][ 12 ] + "'";
			}
			else
			{
				morada = "''";
			}
			update = update.replaceFirst( "[?]morada", morada );
			String localidade;
			if( empresas[ t ][ 13 ] != null )
			{
				localidade = "'" + empresas[ t ][ 13 ] + "'";
			}
			else
			{
				localidade = "''";
			}
			update = update.replaceFirst( "[?]localidade", localidade );
			String codigoPostal;
			if( empresas[ t ][ 14 ] != null )
			{
				codigoPostal = "'" + empresas[ t ][ 14 ] + "'";
			}
			else
			{
				codigoPostal = "''";
			}
			update = update.replaceFirst( "[?]codigo_postal", codigoPostal );
			String distrito;
			if( empresas[ t ][ 15 ] != null )
			{
				distrito = "'" + empresas[ t ][ 15 ] + "'";
			}
			else
			{
				distrito = "''";
			}
			update = update.replaceFirst( "[?]distrito", distrito );
			String concelho;
			if( empresas[ t ][ 16 ] != null )
			{
				concelho = "'" + empresas[ t ][ 16 ] + "'";
			}
			else
			{
				concelho = "''";
			}
			update = update.replaceFirst( "[?]concelho", concelho );
			String email = null;
			if( empresas[ t ][ 18 ] != null )
			{
				try
				{
					Object em[][] = doQuery( softwareConnection, GET_EMAIL + empresas[ t ][ 18 ] );
					if( em != null && em.length > 0 && em[ 0 ][ 0 ] != null )
					{
						email = "'" + (String)em[ 0 ][ 0 ] + "'";
					}
				}
				catch( Exception ex )
				{
				}
			}
			if( email == null )
			{
				email = "''";
			}
			update = update.replaceFirst( "[?]email", email );
			
			String codigo1 = (String) empresas[ t ][ 4 ];
			String codigo2 = (String) empresas[ t ][ 5 ];
			String codigo3 = (String) empresas[ t ][ 6 ];
			String codigo = "'" + ( codigo1 != null ? codigo1 : "_" ) + "/" 
								+ ( codigo2 != null ? codigo2 : "_" ) + "/"
								+ ( codigo3 != null ? codigo3 : "_" ) + "'";
			update = update.replaceFirst( "[?]codigo", codigo );
			update = update.replaceFirst( "[?]perfil_1", "null" );
			update = update.replaceFirst( "[?]perfil_2", "null" );
			update = update.replaceFirst( "[?]perfil_3", "null" );
			update = update.replaceFirst( "[?]servicos", "null" );
			
			queries[ 1 ] = update;
		}
	}
	
	protected Object [][]doQuery( Connection con, String query )
		throws Exception
	{
		return doQuery( con, query, false );
	}
	
	protected Object [][]doQuery( Connection con, String query, boolean isUpdate )
		throws Exception
	{
//		if( con == webConnection )
//		{
//			System.out.println( "WEB" );
//		}
//		else
//		{
//			System.out.println( "LOCAL" );
//		}
//		if( query.indexOf( "INSERT" ) != -1 || query.indexOf( "UPDATE" ) != -1 )
//		{
////			System.out.println( "AAAAAAAAAAAAAHHHHHHH" + query );
//			return new Object[0][0];
//		}
		Statement stm = null;
		stm = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE,
						ResultSet.CONCUR_READ_ONLY );
		if( isUpdate )
		{
			stm.executeUpdate( query );
			return null;
		}
		ResultSet rs = stm.executeQuery( query );
		
		if( rs == null )
		{
			return null;
		}
		ResultSetMetaData rsmd = rs.getMetaData();
		int columns = rsmd.getColumnCount();
		rs.last();
		int rows = rs.getRow();
		Object data[][] = new Object[ rows ][ columns ];
		for( int i = 0; i < rows; ++i )
		{
			rs.absolute( i + 1 );
			for( int j = 0; j < columns; j++ )
			{
				data[ i ][ j ] = rs.getObject( j + 1 );
			}
		}
		return data;
	}
	
	protected static String unicodeToHTML( String text )
	{
		if( text == null || text.length() == 0 )
		{
			return "";
		}

		String output = text;

		output = output.replaceAll( "\\\\u0009", "&nbsp;" );
		output = output.replaceAll( "\\\\u000a", "<br>" );

		output = output.replaceAll( "\\\\u00a0", "&nbsp;" );

		output = output.replaceAll( "\\\\u00c0", "&Agrave;" );
		output = output.replaceAll( "\\\\u00c1", "&Aacute;" );
		output = output.replaceAll( "\\\\u00c2", "&Acirc;" );
		output = output.replaceAll( "\\\\u00c3", "&Atilde;" );
		output = output.replaceAll( "\\\\u00c7", "&Ccedil;" );
		output = output.replaceAll( "\\\\u00c8", "&Egrave;" );
		output = output.replaceAll( "\\\\u00c9", "&Eacute;" );
		output = output.replaceAll( "\\\\u00ca", "&Ecirc;" );
		output = output.replaceAll( "\\\\u00cc", "&Igrave;" );
		output = output.replaceAll( "\\\\u00cd", "&Iacute;" );
		output = output.replaceAll( "\\\\u00ce", "&Icirc;" );
		output = output.replaceAll( "\\\\u00d2", "&Ograve;" );
		output = output.replaceAll( "\\\\u00d3", "&Oacute;" );
		output = output.replaceAll( "\\\\u00d4", "&Ocirc;" );
		output = output.replaceAll( "\\\\u00d5", "&Otilde;" );
		output = output.replaceAll( "\\\\u00d9", "&Ugrave;" );
		output = output.replaceAll( "\\\\u00da", "&Uacute;" );
		output = output.replaceAll( "\\\\u00db", "&Ucirc;" );

		output = output.replaceAll( "\\\\u00e0", "&agrave;" );
		output = output.replaceAll( "\\\\u00e1", "&aacute;" );
		output = output.replaceAll( "\\\\u00e2", "&acirc;" );
		output = output.replaceAll( "\\\\u00e3", "&atilde;" );
		output = output.replaceAll( "\\\\u00e7", "&ccedil;" );
		output = output.replaceAll( "\\\\u00e8", "&egrave;" );
		output = output.replaceAll( "\\\\u00e9", "&eacute;" );
		output = output.replaceAll( "\\\\u00ea", "&ecirc;" );
		output = output.replaceAll( "\\\\u00ec", "&igrave;" );
		output = output.replaceAll( "\\\\u00ed", "&iacute;" );
		output = output.replaceAll( "\\\\u00ee", "&icirc;" );
		output = output.replaceAll( "\\\\u00f2", "&ograve;" );
		output = output.replaceAll( "\\\\u00f3", "&oacute;" );
		output = output.replaceAll( "\\\\u00f4", "&ocirc;" );
		output = output.replaceAll( "\\\\u00f5", "&otilde;" );
		output = output.replaceAll( "\\\\u00f9", "&ugrave;" );
		output = output.replaceAll( "\\\\u00fa", "&uacute;" );
		output = output.replaceAll( "\\\\u00fb", "&ucirc;" );
		output = output.replaceAll( "\\\\u00aa", "&ordf;" );
		output = output.replaceAll( "\\\\u00ba", "&ordm;" );

		output = output.replaceAll( "\\\\u0153", "&#156;" );

		output = output.replaceAll( "\\\\u2013", "-" );
		output = output.replaceAll( "\\\\u2014", "-" );
		output = output.replaceAll( "\\\\u2018|\\\\u2019", "'" );
		output = output.replaceAll( "\\\\u201c|\\\\u201d", "\"" );

		output = output.replaceAll( "\\\\u2022", "*" );
		output = output.replaceAll( "\\\\u2026", "..." );

		return output;
	}

	
}
