/* 
* Copyright 2016 Agencia Estatal de Administración Tibutaria
*
* Licencia con arreglo a la EUPL, Versión 1.1 o –en cuanto
* sean aprobadas por la Comisión Europea– versiones
* posteriores de la EUPL (la «Licencia»);
* Solo podrá usarse esta obra si se respeta la Licencia.
* Puede obtenerse una copia de la Licencia en:
*  
* https://joinup.ec.europa.eu/software/page/eupl
*  
* Salvo cuando lo exija la legislación aplicable o se acuerde
* por escrito, el programa distribuido con arreglo a la
* Licencia se distribuye «TAL CUAL», SIN GARANTÍAS NI CONDICIONES
* DE NINGÚN TIPO, ni expresasni implícitas.
*
* Véase la Licencia en el idioma concreto que rige los permisos y 
* limitaciones que establece la Licencia.
*/ 

package servidor.datos.base;

import java.io.*;
import java.sql.*;
import java.text.*;
import servidor.datos.*;

public class SentenciaSQL {

   public enum Tipo { UPDATE, INSERT, DELETE }
   private PreparedStatement stmt;
   private transient static final int numSlots = 35;
   Object[] parametros = new Object[numSlots];
   private Tipo tipo;
   private MessageFormat stmtToString = null;
   private String sql;

   public SentenciaSQL(String sqlTxt) {
      try {
         sql = sqlTxt;
         tipo = getTipoSql(sql);
         stmt = BaseDatos.bd().getConnection().prepareStatement(sql,
                 (tipo == Tipo.INSERT ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS));
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   final Tipo getTipoSql(String txt) {
      int p = txt.indexOf(' ');
      String pal = txt.substring(0, p).toUpperCase();
      if(pal.equals("UPDATE")) return Tipo.UPDATE;
      if(pal.equals("INSERT")) return Tipo.INSERT;
      return Tipo.DELETE;
   }

   String generaSqlString() {
      String sqlStr = sql;
      try {
         ParameterMetaData pmm = stmt.getParameterMetaData();
         int num = pmm.getParameterCount();
         for(int i=1;i<=num;i++) {
            String rep = "";
            int n = i-1;
            switch(pmm.getParameterType(i)) {
               case java.sql.Types.TIMESTAMP:
                  rep = "''{" + n + ",date,yyyyMMdd HH:mm:ss}''";
                  break;
               case java.sql.Types.INTEGER:
               case java.sql.Types.NUMERIC:
                  rep = "{" + n + ",number,#}";
                  break;
               default:
                  rep = "''{" + n + "}''";
                  break;
            }
            sqlStr = sqlStr.replaceFirst("\\?", rep);
         }
      } catch(Exception exc) {
         return "";
      }
      return sqlStr;
   }

   public int executeUpdate() {
       if (BaseDatos.bd().recuperacionActivada) {
         grabarDatos();
         return 1;
      }

      try {
         return stmt.executeUpdate();
      } catch (SQLException exc) {
         BaseDatos.bd().activarRecuperacion(exc);
         grabarDatos();
      }
      return 0;
   }

   public ResultSet getGeneratedKeys() throws SQLException {
      return stmt.getGeneratedKeys();
   }

   void setInt(int parameterIndex, int x) {
      try {
         stmt.setInt(parameterIndex, x);
         parametros[parameterIndex - 1] = x;
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   void setString(int parameterIndex, String x) {
      try {
         stmt.setString(parameterIndex, x);
         parametros[parameterIndex - 1] = (x == null ? " " : x);
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   void setTimestamp(int parameterIndex, Timestamp x) {
      try {
         stmt.setTimestamp(parameterIndex, x);
         parametros[parameterIndex - 1] = (x == null ? new Timestamp(0) : x);
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   void setBoolean(int parameterIndex, boolean x) {
      try {
         stmt.setBoolean(parameterIndex, x);
         parametros[parameterIndex - 1] = x ? "1" : "0";
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   void grabarDatos() {
      try {
         PrintStream s = new PrintStream(new FileOutputStream(BaseDatos.pathLogBd, true));
         s.println(toSqlString());
         s.close();
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   public String toSqlString() {
      if(stmtToString == null) {
         stmtToString = new MessageFormat(this.generaSqlString());
      }
      StringBuffer sb = new StringBuffer(500);
      return stmtToString.format(parametros, sb, null).toString();
   }
}

