import java.util.Vector;
import java.util.Calendar;
import java.sql.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.event.TableModelEvent;

/**
 * Title:        ICS Editor Events
 * Description:
 * Copyright:    Copyright (c) 2001
 * Company:      Inferencia
 * @author Willian Charles Balmant
 * @version 1.0
 */

public class NovoEventoTableModel extends AbstractTableModel {
  Connection          connection;
  Statement           statement;
  ResultSet           resultSet;
  String[]            columnHeaders = {};
  Vector		linhas = new Vector();
  ResultSetMetaData   metaData;
  String queryStr;

  public NovoEventoTableModel() {
    this("sun.jdbc.odbc.JdbcOdbcDriver", null);
  }

  public NovoEventoTableModel(String driver, String url) {
    try {
      Class.forName(driver);
      //System.out.println("Enabling Driver "+driver);
    }
    catch (ClassNotFoundException ex) {
      System.err.println("Cannot find the database driver classes.");
      ex.printStackTrace();
    }
	  if(url != null && !url.trim().equals("")) {
      try {
        connection = DriverManager.getConnection(url.trim());
        statement = connection.createStatement();
	  	}
      catch(Exception e) {
        e.printStackTrace();
		  }
	  }
  }

  public void setQuery(String query) {
    this.queryStr = query;
  }
  public void executeQuery() {
    this.executeQuery(this.queryStr);
  }
  public void executeQuery(String query) {
    if (connection == null || statement == null) {
      new AlertDialog("Não existe base de dados para executar a consulta.").show();
      return;
    }
    if(this.queryStr == null)
      this.queryStr = query;
    try {
      resultSet = statement.executeQuery(query);
      metaData = resultSet.getMetaData();

      int numberOfColumns =  metaData.getColumnCount();
      columnHeaders = new String[numberOfColumns];
      // Get the column names and cache them.
      // Then we can close the connection.
      for(int column = 0; column < numberOfColumns; column++) {
        columnHeaders[column] = metaData.getColumnLabel(column+1);
      }
      linhas = new Vector();
      Vector newRow = new Vector();
      for (int i = 1; i <= getColumnCount(); i++) {
        newRow.addElement("");
      }
      linhas.addElement(newRow);
    }
    catch (SQLException ex) {
      new AlertDialog(ex.getMessage()).show();
    }
  }

  public void executeUpdate() throws Exception {
    Vector instructions = new Vector();
    for(int i = 0; i < this.getRowCount(); i++) {
      if(this.getValueAt(i, 0).toString().trim().equals("") || this.getValueAt(i, 1).toString().trim().equals(""))
        throw new Exception("Os campos codigo e/ou inicio são obrigatórios.");

      boolean update = false;
      // necessário para alguns casos em que o resultset é fechado.
      this.statement = this.connection.createStatement();
      // curso já existe ?
      try {
        ResultSet rs = this.statement.executeQuery("SELECT codigo FROM "+metaData.getTableName(1)+" WHERE codigo="+dbRepresentation(0, getValueAt(i, 0))+" and inicio="+dbRepresentation(1, getValueAt(i, 1))+" and (turno="+dbRepresentation(2, getValueAt(i, 2))+" or horario="+dbRepresentation(3, getValueAt(i, 3))+")");
        System.out.println("SELECT codigo FROM "+metaData.getTableName(1)+" WHERE codigo="+dbRepresentation(0, getValueAt(i, 0))+" and inicio="+dbRepresentation(1, getValueAt(i, 1))+" and (turno="+dbRepresentation(2, getValueAt(i, 2))+" or horario="+dbRepresentation(3, getValueAt(i, 3))+")");
        if(rs.next()) {
          ConfirmBoolean cb = new ConfirmBoolean();
          new ConfirmationDialog("O curso " + this.getValueAt(i,0) + " já existe!\nDeseja atualizá-lo?", cb).show();
          if(!cb.getState()) continue;
          else update = true;
        }
      }
      catch(SQLException e) {
        e.printStackTrace();
      }

      String sql = (update ? "UPDATE "+metaData.getTableName(1)+" SET " : "INSERT INTO "+metaData.getTableName(1)+" (");
      String values = (update ? "" : "VALUES (");
      String value = "";
      int j;
      for(j = 0; j < this.getColumnCount()-1; j++) {
        value = this.dbRepresentation(j, this.getValueAt(i, j).toString().trim());
        sql += this.getColumnName(j) + (update ? "="+value : "") + ",";
        values += value + ",";
      }
      value = this.dbRepresentation(j, this.getValueAt(i, j));
      sql += this.getColumnName(j) + (update ? "="+value+" WHERE codigo='"+this.getValueAt(i, 0).toString().trim()+"'" : ") ");
      values += value + ")";
      instructions.add(sql+(update ? "" : values));
    }
    for(int i = 0; i < instructions.size(); i++) {
      try {
        System.out.println("Inst: " + instructions.get(i));
        this.statement.executeUpdate(instructions.get(i).toString());
      }
      catch(SQLException e) {
        throw e;
      }
    }
  }

  public void close() throws SQLException {
    if(resultSet != null) resultSet.close();
    if(statement != null) statement.close();
    if(connection != null) connection.close();
  }

  protected void finalize() throws Throwable {
    close();
    super.finalize();
  }

  public String getColumnName(int column) {
    if (columnHeaders[column] != null) {
      return columnHeaders[column];
    } else {
      return "";
    }
  }
  public String[] getColumnNames() {
    return columnHeaders;
  }

  public Class getColumnClass(int column) {
    int type;
    try {
      type = metaData.getColumnType(column+1);
    }
    catch (SQLException e) {
      return super.getColumnClass(column);
    }

    switch(type) {
      case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR:
        return String.class;
      case Types.BIT:
        return Boolean.class;
      case Types.TINYINT: case Types.SMALLINT: case Types.INTEGER:
        return Integer.class;
      case Types.BIGINT:
        return Long.class;
      case Types.FLOAT: case Types.DOUBLE:
        return Double.class;
      case Types.DATE:
        return java.sql.Date.class;
      default:
        return Object.class;
    }
  }

  public boolean isCellEditable(int row, int column) {
    return true;
  }

  public Vector getRows() {
    return linhas;
  }

  public int getColumnCount() {
    return columnHeaders.length;
  }

  public int getRowCount() {
    return linhas.size();
  }

  public Object getValueAt(int aRow, int aColumn) {
    Vector row = (Vector)linhas.elementAt(aRow);
    return row.elementAt(aColumn);
  }

  public String dbRepresentation(int column, Object value) {
    int type;
    if(value != null)
      value = value.toString().trim();

    try {
      type = metaData.getColumnType(column+1);
    }
    catch (SQLException e) {
      return value.toString().trim();
    }

    System.out.println(type);

    switch(type) {
      case Types.INTEGER: case Types.DOUBLE: case Types.FLOAT:
        if(value == null || value.equals(""))
          return "0";
        return value.toString();
      case Types.BIT:
        return ((Boolean)value).booleanValue() ? "1" : "0";
      case Types.CHAR: case Types.VARCHAR:
        if(value == null || value.equals("")) return "'-'";
        return "'"+value+"'";
      case Types.DATE: case Types.TIMESTAMP:
        if(value.equals(""))
          return null;
        try {
          int day = Integer.parseInt(value.toString().substring(0, 2));
          int month = Integer.parseInt(value.toString().substring(3, 5));
          int year = Integer.parseInt(value.toString().substring(6, 10));
          return "#"+(month<10?"0":"")+month+"-"+(day<10?"0":"")+day+"-"+year+"#"; // This will need some conversion.
        }
        catch(NumberFormatException e) {
          e.printStackTrace();
          new AlertDialog("Formato de Data Inválido!\nUse o formato dd/mm/aaaa").show();
          return "erro";
        }
        catch(StringIndexOutOfBoundsException e) {
          e.printStackTrace();
          new AlertDialog("Formato de Data Inválido!\nUse o formato dd/mm/aaaa").show();
          return "erro";
        }
      default:
        return "'-'";
    }
  }

  public void setConnection(String url) {
	  if(url == null || url.trim().equals("")) return;
    try {
      close();
    } catch(SQLException e) {
    }
	  try {
      this.connection = DriverManager.getConnection(url);
      statement = connection.createStatement();
	  }
	  catch(Exception e) {
		  e.printStackTrace();
	  }
  }

  public void removeColumnOrdered() {
    int i = this.queryStr.indexOf(" order by");
    if(i == -1)
      return;
    else
      this.queryStr = this.queryStr.substring(0, i);
    this.executeQuery();
  }

  public void setColumnOrdered(int column) {
    if(column < 0 || column >= this.getColumnCount())
      return;
    int i = this.queryStr.indexOf("order by");
    if(i == -1)
      this.queryStr += " order by " + this.getColumnName(column);
    else{
      if(this.queryStr.endsWith(this.getColumnName(column)))
        this.queryStr = this.queryStr.substring(0, i+9) + this.getColumnName(column) + " DESC";
      else
        this.queryStr = this.queryStr.substring(0, i+9) + this.getColumnName(column);
    }
    this.executeQuery();
  }

  public void setValueAt(Object value, int row, int column) {
		/* Aqui vai o código executado ao editar uma célula */
    ((Vector)linhas.elementAt(row)).setElementAt(value, column);
  }

  public void addRow() {
    Vector newRow = new Vector();
    for (int i = 1; i <= getColumnCount(); i++) {
      newRow.addElement("");
    }
    linhas.addElement(newRow);
    this.fireTableChanged(new TableModelEvent(this));  // Tell the listeners a new table has arrived.
  }

  public void addRowAt(int index) {
    Vector newRow = new Vector();
    for (int i = 1; i <= getColumnCount(); i++) {
      newRow.addElement("");
    }
    linhas.add(index, newRow);
    this.fireTableChanged(new TableModelEvent(this));  // Tell the listeners a new table has arrived.
  }
  public void removeRow(int index) {
    linhas.removeElementAt(index);
    this.fireTableChanged(new TableModelEvent(this));  // Tell the listeners a new table has arrived.
  }
} 
