/**
   * Metodo que calcula la minima diferencia existente entre los carbonos de un compuesto y las
   * condiciones de busqueda impuestas por el usuario. Se usara para las busquedas sin posicion (con
   * tolerancia), iterativa, vecindad y combinada 1 y sus respectivas subbusquedas.
   *
   * @param id Identificador del compuesto
   * @param desplazamiento Array con los desplazamientos correspondientes a cada condicion de
   *     busqueda
   * @param rango Array con las tolerancias correspondientes a cada condicion de busqueda
   * @param tipo Array con los tipos de los carbonos correspondientes a cada condicion de busqueda
   * @return double Devuelve la diferencia calculada
   */
  public static double diferencia(int id, double[] desplazamiento, String[] rango, String[] tipo) {
    int j = 0;
    String sql = "";

    double temp = 0;
    double dif = 0;

    double[] fin = new double[rango.length];

    // Nos conectamos con la base de datos
    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
      con = Conexion2.conectar();
      stmt = con.createStatement();

      while (j < rango.length) {
        double despsup = desplazamiento[j] + (Double.parseDouble(rango[j]));
        double despinf = desplazamiento[j] - (Double.parseDouble(rango[j]));

        sql =
            "SELECT desplazamiento from carbonos where idMolecular="
                + id
                + " and tipoCarbono='"
                + tipo[j];
        sql += "' and desplazamiento>'" + despinf + "' and desplazamiento<'" + despsup + "'";

        rs = stmt.executeQuery(sql);

        dif = Double.parseDouble(rango[j]);
        dif = dif * dif;
        while (rs.next()) {
          temp = rs.getDouble(1) - desplazamiento[j];
          temp = temp * temp;
          if (temp < dif) dif = temp;
        }

        fin[j] = dif;
        j++;
      }
      rs.close();
      stmt.close();
      Conexion2.desconectar(con);
    } catch (java.sql.SQLException e) {
      System.out.println(
          "Excepcion al realizar diferencia en Datos Espectroscopicos2: " + e.getMessage());
      return -1;
    } catch (java.lang.ClassNotFoundException e) {
      System.out.println(
          "Excepcion al realizar la diferencia en Datos Espectroscopicos2: " + e.getMessage());
      return -1;
    }

    double devolver = 0;
    for (int k = 0; k < fin.length; k++) devolver = devolver + fin[k];
    // SI DEVUELVE VALOR NEGATIVO HA HABIDO ERROR!!!!!!!!!
    return devolver;
  }
  /**
   * Este metodo nos permite hacer una busqueda por subestructura dentro de un conjunto reducido de
   * todos los registros de la base de datos.<br>
   * Este grupo de moleculas en el que se realizara la busqueda viene determinado por un parametro
   * del metodo.<br>
   * <br>
   *
   * @param mol Cadena donde esta guardado el codigo smiles de la subestructura que deberan contener
   *     todas aquellas moleculas que nos devuelva este metodo.
   * @param resultados Array unidimensional con los ids de aquellos registros de la base de datos
   *     entre los que se realizara la busqueda.
   * @param familia Familia a la que deben pertencer los compuestos a buscar.
   * @param subfamilia Subfamilia(o grupo) a la que deben pertencer los compuestos a buscar.
   * @param subsubfamilia Subsubfamilia(o tipo) a la que deben pertencer los compuestos a buscar.
   * @return Object[][] Array bidimensional con la informacion correspondiente a cada uno de los
   *     compuestos que cumplen las condiciones de busqueda, contiene el identificador, el smiles,
   *     el jme y el jmeDesplazamiento. Donde IdMoleculaX, idMoleculaY e idMoleculaZ estaran
   *     contenidos en el array resultados
   */
  public static Object[][] rebusqueda(
      String mol,
      int[] resultados,
      String familia,
      String subfamilia,
      String subsubfamilia,
      String nombre,
      String nombresemi,
      String formula) {

    Object res[][] = null;
    String ids = "";
    String smiles = "";
    String jme = "";
    String jmedes = "";
    String jmenum = "";

    // Preparamos la busqueda por subestructura

    MolSearch s;
    MolHandler mh1;

    try {
      s = new MolSearch();
      s.setStereoCareChecking(false);
      mh1 = new MolHandler(mol);
      s.setQuery(mh1.getMolecule());

    } catch (chemaxon.formats.MolFormatException e) {
      System.out.println("Excepcion en la clase MolHandler (413): " + e.getMessage());
      return null;
    }

    // Construimos la sentencia sql

    String sql =
        "SELECT idMolecular,smiles,jme,jmeDesplazamiento,jmeNumeracion FROM moleculas WHERE estado>0 AND estado<5 ";

    if (!nombre.equals("") && (nombre != null)) sql += " AND nombre LIKE '" + nombre + "' ";

    if (!nombresemi.equals("") && (nombresemi != null))
      sql += " AND nombresemisistematico LIKE '" + nombresemi + "' ";

    if (!familia.equals("") && (familia != null)) sql += " AND familia LIKE '" + familia + "' ";

    if (!subfamilia.equals("") && (subfamilia != null))
      sql += " AND subfamilia LIKE '" + subfamilia + "' ";

    if (!subsubfamilia.equals("") && (subsubfamilia != null))
      sql += " AND subsubfamilia LIKE '" + subsubfamilia + "' ";

    if (!formula.equals("") && (formula != null))
      sql += " AND formulamolecular LIKE '" + formula + "' ";

    sql += "AND ( ";

    for (int i = 0; i < resultados.length; i++) {
      if (i == (resultados.length) - 1) sql += "idMolecular=" + resultados[i];
      else sql += "idMolecular=" + resultados[i] + " OR ";
    }
    sql += ") order by idmolecular";
    // Nos conectamos con la base de datos y ejecutamos la sentencia sql

    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
      con = Conexion2.conectar();
      stmt = con.createStatement();
      rs = stmt.executeQuery(sql);

      // Recorremos las filas que nos resultan de ejecutar la sentencia sql

      while (rs.next()) {
        // Recojemos datos
        int id = rs.getInt(1);
        String micodigo = rs.getString(2);
        String mijme = rs.getString(3);
        String mijmedes = rs.getString(4);
        String mijmenum = rs.getString(5);
        // Determinamos si es una subestructura o no

        MolHandler mh2 = null;
        boolean subestructura = false;
        try {

          mh2 = new MolHandler(micodigo);
          s.setTarget(mh2.getMolecule());

          subestructura = s.isMatching();

        } catch (chemaxon.formats.MolFormatException e) {
          System.out.println("Excepcion en la clase MolHandler (480): " + e.getMessage());
          return null;
        } catch (chemaxon.sss.search.SearchException e) {
          System.out.println("Excepcion en el metodo isMatching:" + e.getMessage());
          return null;
        }

        // En caso de que lo sea guardamos los datos necesarios

        if (subestructura) {
          ids += id + "*";
          smiles += micodigo + "*";
          jme += mijme + "*";
          jmedes += mijmedes + "*";
          jmenum += mijmenum + "*";
        }
      }
      StringTokenizer resultado1 = new StringTokenizer(ids, "*");
      StringTokenizer resultado2 = new StringTokenizer(smiles, "*");
      StringTokenizer resultado3 = new StringTokenizer(jme, "*");
      StringTokenizer resultado4 = new StringTokenizer(jmedes, "*");
      StringTokenizer resultado5 = new StringTokenizer(jmenum, "*");

      int registros = resultado1.countTokens();
      res = new Object[registros][5];

      int indice = 0;
      while (resultado1.hasMoreElements()) {
        res[indice][0] = resultado1.nextToken();
        res[indice][1] = resultado2.nextToken();
        res[indice][2] = resultado3.nextToken();
        res[indice][3] = resultado4.nextToken();
        res[indice][4] = resultado5.nextToken();
        indice++;
      }

      rs.close();
      stmt.close();
      Conexion2.desconectar(con);

    } catch (java.sql.SQLException e) {
      System.out.println("Excepcion al realizar la busqueda: " + e.getMessage());
      return null;
    } catch (java.lang.ClassNotFoundException e) {
      System.out.println("Excepcion al realizar la busqueda: " + e.getMessage());
      return null;
    }

    return res;
  }
  /**
   * Este metodo es igual que el de arriba pero solo retorna los idMoleculares reduciendo el tiempo
   * de busqueda
   *
   * <p>Este metodo permitira realizar una busqueda por subestructura molecular dentro de todos los
   * registros de la base de datos.<br>
   * <br>
   *
   * @param mol Cadena donde esta guardado el codigo smiles de la subestructura que deberan contener
   *     todas aquellas moleculas que nos devuelva este metodo.
   * @param familia Familia a la que deben pertencer los compuestos a buscar.
   * @param subfamilia Subfamilia(o grupo) a la que deben pertencer los compuestos a buscar.
   * @param subsubfamilia Subsubfamilia(o tipo) a la que deben pertencer los compuestos a buscar.
   * @return Object[][] Array bidimensional con la informacion correspondiente a cada uno de los
   *     compuestos que cumplen las condiciones de busqueda, contiene el identificador, el smiles,
   *     el jme y el jmeDesplazamiento. r>
   */
  public static Object[][] busquedaIds(
      String mol,
      String familia,
      String subfamilia,
      String subsubfamilia,
      String nombre,
      String nombresemi,
      String formula) {

    Object[][] res = null;
    String ids = "";

    // Preparamos la busqueda por subestructura

    MolSearch s;
    MolHandler mh1;

    try {
      s = new MolSearch();
      s.setStereoCareChecking(false);
      mh1 = new MolHandler(mol);
      s.setQuery(mh1.getMolecule());

    } catch (chemaxon.formats.MolFormatException e) {
      System.out.println("Excepcion en la clase MolHandler (214): " + e.getMessage());
      return null;
    }

    String sql = "SELECT idMolecular,smiles FROM moleculas where estado>0 AND estado<5";

    if (nombre != null) if (!nombre.equals("")) sql += " AND nombre LIKE '" + nombre + "' ";

    if (nombresemi != null)
      if (!nombresemi.equals("")) sql += " AND nombresemisistematico LIKE '" + nombresemi + "' ";

    if (familia != null) if (!familia.equals("")) sql += " AND familia LIKE '" + familia + "' ";

    if (subfamilia != null)
      if (!subfamilia.equals("")) sql += " AND subfamilia LIKE '" + subfamilia + "' ";

    if (subsubfamilia != null)
      if (!subsubfamilia.equals("")) sql += " AND subsubfamilia LIKE '" + subsubfamilia + "' ";

    if (formula != null)
      if (!formula.equals("")) sql += " AND formulamolecular LIKE '" + formula + "' ";

    sql += " order by idmolecular";

    // Nos conectamos con la base de datos y ejecutamos la sentencia sql

    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {

      con = Conexion2.conectar();
      stmt = con.createStatement();
      rs = stmt.executeQuery(sql);

      // Recorremos las filas que nos resultan de ejecutar la sentencia sql

      while (rs.next()) {
        // Recogemos datos
        int id = rs.getInt(1);
        String micodigo = rs.getString(2);
        // Determinamos si es una subestructura o no
        MolHandler mh2;
        boolean subestructura = false;
        try {
          mh2 = new MolHandler(micodigo);
          s.setTarget(mh2.getMolecule());
          subestructura = s.isMatching();

        } catch (chemaxon.formats.MolFormatException e) {
          System.out.println("Excepcion en la clase MolHandler (276): " + e.getMessage());
          e.printStackTrace(System.out);
          return null;
        } catch (chemaxon.sss.search.SearchException e) {
          System.out.println("Excepcion en el metodo isMatching:" + e.getMessage());
          return null;
        }

        // En caso de que lo sea guardamos los datos necesarios

        if (subestructura) {
          ids += id + "*";
        }
      }

      StringTokenizer resultado1 = new StringTokenizer(ids, "*");

      int registros = resultado1.countTokens();

      res = new Object[registros][2];

      int indice = 0;
      while (resultado1.hasMoreElements()) {
        res[indice][0] = resultado1.nextToken();
        indice++;
      }

      rs.close();
      stmt.close();
      Conexion2.desconectar(con);

    } catch (java.sql.SQLException e) {
      System.out.println("Excepcion al realizar la busqueda: " + e.getMessage());
      return null;
    } catch (java.lang.ClassNotFoundException e) {
      System.out.println("Excepcion al realizar la busqueda: " + e.getMessage());
      return null;
    }

    return res;
  }
  /**
   * Metodo que calcula la minima diferencia existente entre los carbonos de un compuesto y las
   * condiciones de busqueda impuestas por el usuario. Se usara para las busquedas con posicion y
   * sin tolerancia y su respectiva subbusquedas.
   *
   * @param id Identificador del compuesto
   * @param numeracion Array con las posiciones de los carbonos correspondientes a cada condicion de
   *     busqueda.
   * @param desplazamientoInf Array con los desplazamientos inferiores correspondientes a cada
   *     condicion de busqueda
   * @param desplazamientoSup Array con los desplazamientos superiores correspondientes a cada
   *     condicion de busqueda
   * @param tipo Array con los tipos de los carbonos correspondientes a cada condicion de busqueda
   * @return double Devuelve la diferencia calculada
   */
  public static double diferencia(
      int id,
      String[] numeracion,
      double[] desplazamientoInf,
      double[] desplazamientoSup,
      String[] tipo) {
    int j = 0;
    String sql = "";

    double temp = 0;
    double dif = 0;
    double desplazamiento = 0;

    double[] fin = new double[tipo.length];

    StringBuffer[] num = new StringBuffer[numeracion.length];

    for (int z = 0; z < numeracion.length; z++) {
      StringBuffer nueva = new StringBuffer();
      int t = 0;
      while (t < numeracion[z].length()) {
        if (numeracion[z].charAt(t) == 39) {
          nueva.append((char) 92);
          nueva.append((char) 39);
        } else {
          nueva.append(numeracion[z].charAt(t));
        }

        num[z] = nueva;
        t++;
      }
    }

    // Nos conectamos con la base de datos
    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
      con = Conexion2.conectar();
      stmt = con.createStatement();

      while (j < tipo.length) {

        sql =
            "SELECT desplazamiento from carbonos where idMolecular="
                + id
                + " and tipoCarbono='"
                + tipo[j];
        sql += "' AND numeracion='" + num[j];
        sql +=
            "' and desplazamiento>'"
                + desplazamientoInf[j]
                + "' and desplazamiento<'"
                + desplazamientoSup[j]
                + "'";

        rs = stmt.executeQuery(sql);

        dif = desplazamientoSup[j] - desplazamientoInf[j];
        desplazamiento = desplazamientoInf[j] + (dif / 2);
        dif = dif * dif;
        while (rs.next()) {
          temp = rs.getDouble(1) - desplazamiento;
          temp = temp * temp;
          if (temp < dif) dif = temp;
        }

        fin[j] = dif;
        j++;
      }
      rs.close();
      stmt.close();
      Conexion2.desconectar(con);
    } catch (java.sql.SQLException e) {
      System.out.println(
          "Excepcion al realizar diferencia en Datos Espectroscopicos2: " + e.getMessage());
      return -1;
    } catch (java.lang.ClassNotFoundException e) {
      System.out.println(
          "Excepcion al realizar la diferencia en Datos Espectroscopicos2: " + e.getMessage());
      return -1;
    }

    double devolver = 0;
    for (int k = 0; k < fin.length; k++) devolver = devolver + fin[k];
    // SI DEVUELVE VALOR NEGATIVO HA HABIDO ERROR!!!!!!!!!
    return devolver;
  }