package sac.gui.handler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;


import sac.doenca.Doenca;
import sac.exception.InvalidArgumentException;
import sac.fachada.SACFachada;
import sac.gui.bean.PreOperationPFBean;
import sac.gui.bean.EnderecoBean;
import sac.gui.bean.ThinDoencaBean;
import sac.gui.bean.PessoaFisicaBean;
import sac.persistencia.PersistenceException;
import sac.pessoa.endereco.Endereco;
import sac.pessoa.fisica.FiltroBuscaPessoaFisica;
import sac.pessoa.fisica.PessoaFisica;

/**
 * Handler para o consulta por Pessoa Fisica no sistema.
 *
 * @author rtr
 */

public class ConsultaPFHandler extends SACHandler {

    /** Guarda o mapeamento (operacao, Handler)
     */
    protected Map functionImplementers;

    /** Guarda o último handler solicitado.
     */
    protected SACHandler currentImplementer;

    /** Guarda a última operação solicitada.
     */
    protected String currentFunction;

    private final String CONSULTA_OPERATION = "CONSULTA_OPERATION";
    private final String PRE_OPERATION = "PRE_OPERATION";


    private final String URL_CONSULTA_PF = "/jsp/consultaPF.jsp";
    private final String PRE_OPERATION_PF_BEAN_REQUEST = "preOperationPF";
    private static final String RESPOSTA_PF_BEAN_REQUEST = "resposta_consultaPF";
    private static final String MESSAGE_ERRO_REQUEST = "mensagem_erro";

    private static final String QUERY_INPUT = "query";
    private static final String START_INPUT = "start";
    private static final String SIZE_INPUT = "size";
    private static final String TYPE_INPUT = "tipo_consulta";

    public ConsultaPFHandler() {
        super();
        this.functionImplementers = new Hashtable();

        init();
    }

    private void init() {

        // preenchendo a funcao de operacoes do Handler
        functionImplementers.put(CONSULTA_OPERATION, new ConsultaHandler());
        functionImplementers.put(PRE_OPERATION, new PreencherFormHandler());
    }


    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    * @param fachada fachada do Sistema
    * @return String a url do form a ser retornado
    */
    public  String processRequest(HttpServletRequest request, HttpServletResponse response, SACFachada fachada)
            throws ServletException, IOException {
        String functionName = request.getParameter(SACHandler.FUNCTION_ID);
        String result = null;
        SACHandler handler;

        if (functionName.equals(currentFunction)) {
            handler = currentImplementer;
        } else {
            handler = (SACHandler) functionImplementers.get(functionName);
            this.currentFunction = functionName;
            this.currentImplementer = handler;
        }
        if (handler != null) {
            result = handler.processRequest(request, response, fachada);
        } else {
            System.out.println("Nao conseguiu obter o handler " + functionName);
        }
        return result;
    }

    public String preencherFormPadrao(HttpServletRequest request,
        SACFachada fachada) throws ServletException {
        PreOperationPFBean prePF;
        try {
            prePF = createPreOperationBean(fachada);
        } catch ( PersistenceException pe){
            throw new ServletException ("Nao foi possivel criar Bean, "+ pe.getMessage() );
        }
        request.setAttribute(QUERY_INPUT, "");
        request.setAttribute(START_INPUT, new Integer(0) );
        request.setAttribute(SIZE_INPUT, new Integer(10) );
        request.setAttribute(TYPE_INPUT, "");
//        request.setAttribute("has_next", new Boolean(false));
//        request.setAttribute(RESPOSTA_PF_BEAN_REQUEST, new ArrayList());
//                      request.setAttribute(MESSAGE_ERRO_REQUEST, "init");
        request.setAttribute(PRE_OPERATION_PF_BEAN_REQUEST, prePF);
        return URL_CONSULTA_PF;
    }

    private PreOperationPFBean createPreOperationBean ( SACFachada fachada)
        throws PersistenceException {
        List listaDoencas = fachada.listarDoencas();
        List listaserv = fachada.listarServicos();

        ThinDoencaBean[] lstThinDoenca = new ThinDoencaBean[listaDoencas.size()] ;
        for (int i = 0; i < listaDoencas.size(); i++) {
            Doenca d = (Doenca) listaDoencas.get(i);
             lstThinDoenca[i] = new ThinDoencaBean(d.getNome(),
                d.getId().getLongValue());
        }

        String[] servicos = new String[listaserv.size()];
        servicos = (String[])listaserv.toArray(servicos);

        return  new PreOperationPFBean( lstThinDoenca, servicos);
    }

    /**
     * Handler para a operacao de consulta de Pessoa física no sistema.
     */
    private class ConsultaHandler extends SACHandler {

        private static final String NOME_INPUT = "nome";
        private static final String DOENCA_INPUT = "doenca";
        private static final String SERVICO_INPUT = "servico";
//        private static final String TIPO_CONSULTA_INPUT = "tipo_consulta";
//
//        private static final String SIZE_CONSULTA_INPUT = "size";
//        private static final String START_CONSULTA_INPUT = "start";

        /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
        * @param request servlet request
        * @param response servlet response
        * @param fachada fachada do Sistema
        * @return String a url do form a ser retornado
        */
        public String processRequest(HttpServletRequest request,
            HttpServletResponse response, SACFachada fachada)
            throws ServletException, IOException {

            try {

                request.setAttribute( NOME_INPUT, request.getAttribute(NOME_INPUT));
                request.setAttribute( DOENCA_INPUT, request.getAttribute(DOENCA_INPUT));
                request.setAttribute( SERVICO_INPUT, request.getAttribute(SERVICO_INPUT));

                request.setAttribute(PRE_OPERATION_PF_BEAN_REQUEST, createPreOperationBean(fachada));

                String query = request.getParameter(QUERY_INPUT);
                String tipo_consulta =  request.getParameter(TYPE_INPUT);

                String sizeStr = request.getParameter(SIZE_INPUT);
                String startIndexStr = request.getParameter(START_INPUT);



                FiltroBuscaPessoaFisica filtro;
                int tipo;
                if ( query != null && !query.equals("")) {
                    if ( "nome".equals( tipo_consulta)){
                        tipo = FiltroBuscaPessoaFisica.consultaPorNome;
                    } else if ( "doenca".equals( tipo_consulta)){
                        tipo = FiltroBuscaPessoaFisica.consultaPorDoenca;
                    } else if ( "servico".equals( tipo_consulta)){
                        tipo = FiltroBuscaPessoaFisica.consultaPorTipoServico;
                    } else {
                        request.setAttribute(MESSAGE_ERRO_REQUEST,
                            "Nenhum tipo de consulta foi selecionado..");
                        System.out.println("Nenhum tipo de consulta foi selecionado..");
                        return URL_CONSULTA_PF;
                    }
                } else {
                        request.setAttribute(MESSAGE_ERRO_REQUEST,
                            "Consulta em banco, Preencha a sua consulta.");
                        System.out.println("Consulta em banco, Preencha a sua consulta.");
                        return URL_CONSULTA_PF;
                }
                filtro = new FiltroBuscaPessoaFisica(query, tipo);
                int size, start;
                size = Integer.valueOf(sizeStr).intValue();
                start = Integer.valueOf(startIndexStr).intValue();

                List listaPessoas = fachada.consultaPessoaFisica( filtro, start, size +1);

                List pessoasbean = new ArrayList();
                boolean has_next = listaPessoas.size() > size;
                int tamanho_apresentacao = (has_next)? listaPessoas.size()-1 : listaPessoas.size();
                for (int i = 0; i < tamanho_apresentacao ; i++) {
                    PessoaFisica pessoa = (PessoaFisica) listaPessoas.get(i);
                    pessoasbean.add( createPessoaFisicaBean( pessoa));
                }

                request.setAttribute(QUERY_INPUT, query);
                request.setAttribute(START_INPUT, new Integer(start) );
                request.setAttribute(SIZE_INPUT, new Integer(size) );
                request.setAttribute("has_next", new Boolean(has_next));
                request.setAttribute( TYPE_INPUT, tipo_consulta);

                request.setAttribute(RESPOSTA_PF_BEAN_REQUEST, pessoasbean);

                return URL_CONSULTA_PF;
            } catch (PersistenceException pe ){
                throw new ServletException("Nao foi possivel realizar a consulta,"+
                    pe.getMessage());
            } catch (InvalidArgumentException iae){
                throw new ServletException("Erro Interno,"+ iae.getMessage());
            }
        }

        private PessoaFisicaBean createPessoaFisicaBean (PessoaFisica pessoa){
            List doencas = pessoa.getDoencas();
            ThinDoencaBean[] doencasbean =
                new ThinDoencaBean[doencas.size()] ;
            for (int i = 0; i < doencas.size(); i++) {
                Doenca d = (Doenca) doencas.get(i);
                 doencasbean[i] = new ThinDoencaBean(d.getNome(),
                 d.getId().getLongValue());
            }
            Endereco endereco = pessoa.getEndereco();
            EnderecoBean enderecobean = new EnderecoBean (endereco.getRua(),
                endereco.getBairro(), endereco.getCidade(),
                endereco.getEstado(), endereco.getPais(), endereco.getCep(),
                endereco.getTelefone(), endereco.getEmail() );

            return new PessoaFisicaBean (pessoa.getNome(),
                pessoa.getCpf(), enderecobean ,
                (String[]) pessoa.getTiposServicos().toArray(
                    new String[pessoa.getTiposServicos().size()]),
                doencasbean, pessoa.getDescricaoAtividades() );
        }

    }

    /**
     * Handler para a operacao de preencher campos defalut na consultar por Pessoa física.
     */
    private class PreencherFormHandler extends SACHandler {

        /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
        * @param request servlet request
        * @param response servlet response
        * @param fachada fachada do Sistema
        * @return String a url do form a ser retornado
        */
        public String processRequest(HttpServletRequest request, HttpServletResponse response,
               SACFachada fachada) throws ServletException, IOException {

            return preencherFormPadrao(request, fachada);
        }
    }
}