package versao2.persistencia.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import versao2.dominio.Cliente;
import versao2.dominio.ItemPedido;
import versao2.dominio.Pedido;
import versao2.persistencia.DAO;
import versao2.persistencia.DBUtil;
import versao2.persistencia.PedidoDAO;

/**
 * Implementacao do objeto de acesso a dados para a classe Pedido.
 *
 * @see  versao2.persistencia.PedidoDAO
 */
public final class PedidoDAOImpl
    implements PedidoDAO {

  /*
     Singleton de escopo limitado
     Note que apesar de possuir uma unica instancia desta clase,
     este objeto nao e global.
     Como getInstance e um metodo protegido,
     apenas membros do mesmo pacote podem obter instancias dele diretamente.
   */
  private static PedidoDAOImpl instance;

  static {
    instance = new PedidoDAOImpl();
  }

  protected static PedidoDAO getInstance() {
    return instance;
  }

  private PedidoDAOImpl(){}

  private void create(Pedido pedido) throws SQLException {
    if (!pedido.validate()) {
      throw new IllegalStateException("BUG: Estado do objeto ilegal.");
    }
    Connection conn = DBUtil.getConnection();
    PreparedStatement pstmt = conn.prepareStatement(
        "INSERT INTO PEDIDO (DATAEMISSAO,CLIENTEID) VALUES (?,?)");
    pstmt.setDate(1, new java.sql.Date(pedido.getDataEmissao().getTime()));
    pstmt.setLong(2, pedido.getCliente().getClienteId());
    pstmt.executeUpdate();
    ResultSet rs = pstmt.getGeneratedKeys();
    if (rs.next()) {
      pedido.setPedidoId(rs.getLong(1));
    }
    atualizarItems(pedido);
    conn.close();
  }

  private void update(Pedido pedido) throws SQLException {
    Connection conn = DBUtil.getConnection();
    PreparedStatement pstmt = conn.prepareStatement(
        "UPDATE PEDIDO SET CLIENTEID=?,DATAEMISSAO=? WHERE PEDIDOID=?"
        );
    pstmt.setLong(1, pedido.getCliente().getClienteId());
    pstmt.setDate(2, new java.sql.Date(pedido.getDataEmissao().getTime()));
    pstmt.setLong(3, pedido.getPedidoId());
    pstmt.execute();
    conn.close();
  }

  public void save(Pedido pedido) throws SQLException {
    if (pedido.getPedidoId() == UNSAVED) {
      create(pedido);
    }
    else {
      update(pedido);
    }
  }

  public List /*Pedido*/ buscarPorCliente(Cliente cliente) throws
      SQLException {
    Pedido pedido = null;
    List result = new ArrayList();

    Connection conn = DBUtil.getConnection();
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM PEDIDO WHERE CLIENTEID = " +
                                     cliente.getClienteId());
    while (rs.next()) {
      pedido = new Pedido();
      pedido.setCliente(cliente);
      pedido.setPedidoId(rs.getLong("PEDIDOID"));
      pedido.setDataEmissao(rs.getDate("DATAEMISSAO"));
      carregarItems(pedido);
      result.add(pedido);
    }
    conn.close();
    return result;
  }

  public void removerPorCliente(Cliente cliente) throws SQLException {
    Connection conn = DBUtil.getConnection();
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("DELETE FROM PEDIDO WHERE CLIENTEID = " + cliente.getClienteId());
    conn.close();
  }


  private void atualizarItems(Pedido pedido) throws SQLException {
    removerItems(pedido);
    salvarItems(pedido);
  }

  private void carregarItems(Pedido pedido) throws SQLException {
    List
    /*ItemPedido*/ result = new ArrayList();
    ItemPedido item = null;

    Connection conn = DBUtil.getConnection();
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM ITEM WHERE PEDIDOID =" +
                                     pedido.getPedidoId());
    while (rs.next()) {
      item = new ItemPedido();
      item.setItem(rs.getString("ITEM"));
      item.setQuatidade(rs.getInt("QUANTIDADE"));
      item.setPrecoUn(rs.getFloat("VALOR"));
      result.add(item);
    }
    pedido.setItems(result);
  }

  private void removerItems(Pedido pedido) throws SQLException {
    Connection conn = DBUtil.getConnection();
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("DELETE FROM ITEM WHERE PEDIDOID = " + pedido.getPedidoId());
    conn.close();

  }

  private void salvarItems(Pedido pedido) throws SQLException {
    Connection conn = DBUtil.getConnection();
    PreparedStatement pstmt = conn.prepareStatement(
        "INSERT INTO ITEM (PEDIDOID,ITEM,QUANTIDADE,VALOR) VALUES (?,?,?,?)");
    pstmt.setLong(1, pedido.getPedidoId());
    for (Iterator iter = pedido.getItems().iterator(); iter.hasNext(); ) {
      ItemPedido item = (ItemPedido) iter.next();
      pstmt.setString(2, item.getItem());
      pstmt.setInt(3, item.getQuatidade());
      pstmt.setFloat(4, item.getPrecoUn());
      pstmt.executeUpdate();
    }
  }


}
