/*
 *  iReport  --  Visual designer for generating JasperReports Documents
 *  Copyright (C) 2002  Giulio Toffoli gt@businesslogic.it
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Giulio Toffoli
 *  Via T.Aspetti, 233
 *  35100 Padova ITALY
 *  gt@businesslogic.it
 */
package com.businesslogic.ireport.ui;

import com.businesslogic.ireport.*;

import com.ms.wfc.app.*;
import com.ms.wfc.core.*;
import com.ms.wfc.ui.*;
import com.ms.wfc.html.*;

import java.util.*;
import java.sql.*;

/**
 * Questa classe puņ accettare un numero variabile di parametri sulla riga
 * di comando. L'esecuzione del programma inizia con il metodo main(). Il costruttore
 * della classe non viene richiamato fino a quando un oggetto di tipo "ElaborationForm"
 * non viene creato nel metodo main().
 */
public class ElaborationForm extends Form implements Runnable 
{
	Vector fields;
	boolean first=true;
	ConnectionEntry ce;
	String password;
	String query;
	Thread t;
	MainForm mf = null;
	public boolean use_JDK = true;
	boolean error=false;
	
	public ElaborationForm(MainForm mf)
	{
		super();

		// Necessario per il supporto della finestra di progettazione form di Visual J++
		initForm();		
		// TODO: aggiungere il codice del costruttore dopo la chiamata di initForm.
		fields = new Vector();
		this.mf = mf;
	}

	/**
	 * ElaborationForm esegue l'overriding di dispose e quindi puņ svuotare
	 * l'elenco dei componenti.
	 */
	public void dispose()
	{
		super.dispose();
		components.dispose();
	}

	private void ElaborationForm_activate(Object source, Event e)
	{
		if (first)
		{
			first=false;
			t = new Thread(this);
			t.start();
			t.setPriority(t.MAX_PRIORITY);
			Thread.currentThread().yield();
		}
	}
	
	public void setConnectionEntry(ConnectionEntry ce)
	{
		this.ce = ce;
	}
	
	public void setPassword(String password)
	{
		this.password = password;
	}
	
	public void setQuery(String query)
	{
		this.query = query;
	}
	
	public Vector getFields()
	{
		return fields;
	}
	
	
	public void run()
	{
		if (!use_JDK)
		{
					
			try {				
				Class.forName(ce.driverClass  );
				Connection conn = DriverManager.getConnection(ce.url,
				ce.username,
				password); 
				
				Statement stmt = conn.createStatement();
				String select = query;
				ResultSet rs01 = stmt.executeQuery(select);
				ResultSetMetaData rsmd01 = rs01.getMetaData();
				
				
				for (int i=1; i <=rsmd01.getColumnCount(); ++i)
				{
					JRField f = new JRField(rsmd01.getColumnName(i),getJdbcTypeClass(rsmd01.getColumnType(i) ) );
					//DataListItem dli = new DataListItem(f, f.name,0);
					//dli.setSubItem(0,f.classType);
					//listViewFields.addItem(dli);
					fields.addElement(f);
				}
			}catch (NoClassDefFoundError ex)
			{
				error = true;
				MessageBox.show("NoClassDefFoundError!!\nCheck your classpath!","Errore",MessageBox.ICONERROR);
				this.setDialogResult(DialogResult.CANCEL);	
				return;					
			} 
			catch (ClassNotFoundException ex)
			{
				error = true;
				MessageBox.show("ClassNotFoundError:\n"+ ex.getMessage() +"\n\nCheck your classpath!","Errore",MessageBox.ICONERROR);
				this.setDialogResult(DialogResult.CANCEL);
				return;				
			} 
			catch (java.sql.SQLException ex)
			{
				error = true;
				MessageBox.show("SQL problems:\n"+ex.getMessage(),"Errore",MessageBox.ICONERROR);
				this.setDialogResult(DialogResult.CANCEL);	
				return;				
			} 
			catch (Exception ex)
			{
				error = true;
				MessageBox.show("General problem:\n"+ex.getMessage()+"\n\nControllare nome utente e password, e che il DBMS sia attivo!","Errore",MessageBox.ICONERROR);
				this.setDialogResult(DialogResult.CANCEL);	
				return;
			}
		}
		else
		{
			/***************************************
			 * USING JAVA.EXE
			 **********************************/
			String ext = "";
			String cmd = com.ms.wfc.io.File.combine( (String) mf.connProperties.get("JAVA_HOME") , "bin\\java.exe") + " IReportJDBCConnector ";
			cmd +=" -jdriver" + ce.driverClass +" -juser"+ce.username+" -jpasswd"+password+" -jurl"+ce.url;
			cmd += " -query \""+ query +"\" ";
			
			Vector result = execute(cmd,true);
			if (result != null)
			{
			
				
				if ( ((String)result.elementAt(0)).equals("SUCCESS"))
				{
					String s="";
					for (int i=1; i< result.size(); ++i)
					{
						s = (String)result.elementAt(i);
						if (s.indexOf("--") < 0) continue;
						
						JRField f = new JRField(s.substring(0, s.indexOf("--")), s.substring( s.indexOf("--")+2));
						//DataListItem dli = new DataListItem(f, f.name,0);
						//dli.setSubItem(0,f.classType);
						//listViewFields.addItem(dli);
						fields.addElement(f);
					}
					//MessageBox.show(s);
					
					
				}
				else
				{
					String s="ERRORRRRR!\n";
					for (int i=1; i< result.size(); ++i)
					{
						s += (String)result.elementAt(i)+"\n";
					}
					MessageBox.show(s);
					this.setDialogResult(DialogResult.CANCEL);	
					return;
				}
					
			}
		}

		this.setDialogResult(DialogResult.OK);
		return;
	}

		/**
	 * Thanx to Jackie Manning j.m@programmer.net for this method!!
	 */
	 public static String getJdbcTypeClass( int t ) {
        String cls = "java.lang.String";
        switch( t ) {
            case java.sql.Types.TINYINT:
            case java.sql.Types.BIT:
                cls = "java.lang.Byte";
                break;
            case java.sql.Types.SMALLINT:
                cls = "java.lang.Short";
                break;
            case java.sql.Types.INTEGER:
                cls = "java.lang.Integer";
                break;
            case java.sql.Types.REAL:
            case java.sql.Types.DOUBLE:
            case java.sql.Types.NUMERIC:
            case java.sql.Types.DECIMAL:
                cls = "java.lang.Double";
                break;
            case java.sql.Types.CHAR:
            case java.sql.Types.VARCHAR:
                cls = "java.lang.String";
                break;

            case java.sql.Types.BIGINT:
                cls = "java.lang.Long";
                break;
            case java.sql.Types.DATE:
            case java.sql.Types.TIME:
                cls = "java.util.Date";
                break;
            case java.sql.Types.TIMESTAMP:
                cls = "java.sql.Timestamp";
                break;
        }
        return cls;
    }
	 
	private void button1_click(Object source, Event e)
	{
		t.stop();
		this.setDialogResult(DialogResult.CANCEL);	
		this.dispose();
		return;
	}

	private void timer1_timer(Object source, Event e)
	{
		if (error) this.dispose();
		int val = this.progressBar1.getValue();
			val ++;
			if (val > this.progressBar1.getMaximum())
				val = 0;
			this.progressBar1.setValue(val);
		Thread.yield();
	}
	
	
	public Vector execute(String cmd, boolean wait)
	{
		int ret = 0;
		Vector rows = new Vector();
		try {
				java.lang.Runtime rt = java.lang.Runtime.getRuntime();
				java.lang.Process p = rt.exec( cmd);
				//java.io.InputStream is = p.getErrorStream();
				java.io.InputStream is2 = p.getInputStream();
				
				int b;
				long count;
				count = 0;
				String row="";
				while ((b=is2.read()) != -1)
				{
					if (b != '\n')
					{
						row += new String(new byte[]{(byte)b});
					}
					else 
					{
						rows.addElement(new String(row));
						row="";
					}
				}
				//is.close();
				is2.close();
				
				if (wait)
					p.waitFor();
			} catch (Exception ex)
			{
				ret = -1;
				MessageBox.show(ex.getMessage());
				return null;
			}
			
		return rows;
	}
	

	private void ElaborationForm_mouseMove(Object source, MouseEvent e)
	{
		Thread.yield();
	}

	/**
	 * NOTA: il seguente codice č richiesto dalla finestra di progettazione form 
	 * di Visual J++. Č possibile modificarlo con l'Editor di form.  Non modificarlo
	 * con l'Editor del codice.
	 */
	Container components = new Container();
	ProgressBar progressBar1 = new ProgressBar();
	Label label1 = new Label();
	Button button1 = new Button();
	com.ms.wfc.app.Timer timer1 = new com.ms.wfc.app.Timer(components);

	private void initForm()
	{
		this.setText("ElaborationForm");
		this.setAutoScaleBaseSize(new Point(5, 13));
		this.setBorderStyle(FormBorderStyle.FIXED_TOOLWINDOW);
		this.setClientSize(new Point(302, 92));
		this.setStartPosition(FormStartPosition.CENTER_SCREEN);
		this.addOnMouseMove(new MouseEventHandler(this.ElaborationForm_mouseMove));
		this.addOnActivate(new EventHandler(this.ElaborationForm_activate));

		progressBar1.setLocation(new Point(8, 28));
		progressBar1.setSize(new Point(280, 20));
		progressBar1.setTabIndex(0);
		progressBar1.setText("progressBar1");

		label1.setLocation(new Point(8, 8));
		label1.setSize(new Point(184, 20));
		label1.setTabIndex(1);
		label1.setTabStop(false);
		label1.setText("I\'m getting info. Please wait....");

		button1.setLocation(new Point(108, 60));
		button1.setSize(new Point(84, 24));
		button1.setTabIndex(2);
		button1.setText("Abort");
		button1.addOnClick(new EventHandler(this.button1_click));

		timer1.setEnabled(true);
		timer1.addOnTimer(new EventHandler(this.timer1_timer));
		/* @designTimeOnly timer1.setLocation(new Point(212, 12)); */

		this.setNewControls(new Control[] {
							button1, 
							label1, 
							progressBar1});
	}

	/**
	 * Punto di ingresso principale per l'applicazione. 
	 *
	 * @param args Matrice di parametri passata all'applicazione
	 * tramite la riga di comando.
	 */
	public static void main(String args[])
	{
		Application.run(new ElaborationForm(null));
	}
}
