package sac.gui.handler;

import javax.servlet.*;
import javax.servlet.http.*;

import java.util.List;
import java.util.Vector;
import java.util.Arrays;
import java.util.Map;
import java.io.IOException;
import java.util.Hashtable;

import sac.doenca.Doenca;
import sac.exception.ItemJaCadastradoException;
import sac.exception.ItemNaoCadastradoException;
import sac.exception.InvalidArgumentException;
import sac.exception.NullArgumentException;
import sac.fachada.SACFachada;
import sac.pessoa.fisica.PessoaFisica;
import sac.pessoa.fisica.CPFInvalidoException;
import sac.pessoa.endereco.Endereco;
import sac.persistencia.PersistenceException;
import sac.gui.bean.CadastroPFBean;
import sac.pessoa.SenhaInvalidaException;
import sac.pessoa.UsuarioComum;
import sac.persistencia.OID;

/**
 * Handler para o formulário de login no sistema.
 *
 * @author  fcan, esrb
 */
public class MenuCadastroPFHandler extends SACHandler {

    /** Constante que define o Name do Hidden de um Form que
     * identifica unicamente o Handler que tratará a operação
     * de logar.
     */

    private static final String TODAS_DOENCAS_INPUT = "todas_doencas";
    private static final String TODAS_DOENCASID_INPUT = "todas_doencasid";
    private static final String TODAS_SERVICOS_INPUT = "todas_servicos";

    // FIXME - deve estar num arquivo de propriedades
    private static final String OPERACAO_PREENCHERCADASTRO = "PreencherOperation";
    private static final String OPERACAO_CADASTRO = "CadastroOperation";
    private static final String OPERACAO_ALTERACAO = "AlteracaoOperation";
    private static final String OPERACAO_PREENCHER_TODO_CADASTRO = "PreencherTudoOperation";

    List lstDoencas;
    List lstServicos;

    /** 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;

    /** Creates new MenuHandler */
    public MenuCadastroPFHandler() {
        super();
        this.functionImplementers = new Hashtable();
        this.functionImplementers.put(OPERACAO_PREENCHERCADASTRO, new PreencherCadPFHandler());
        this.functionImplementers.put(OPERACAO_CADASTRO, new CadastroPFHandler());
        this.functionImplementers.put(OPERACAO_ALTERACAO, new AlteracaoPFHandler());
        this.functionImplementers.put(OPERACAO_PREENCHER_TODO_CADASTRO, new PreencherTodoCadPFHandler());
    }

    public List getListaDoencas() {
      return lstDoencas;
    }

    public List getListaServicos() {
      return lstServicos;
    }

    public void setListaDoencas(List doencas) {
      lstDoencas = doencas;
    }

    public void setListaServicos(List servicos) {
      lstServicos = servicos;
    }

    /** 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 sacFachada)
    throws ServletException, IOException {
        try {
            if (getListaDoencas() == null) {
              setListaDoencas( sacFachada.listarDoencas());
            }
            if (getListaServicos() == null) {
              setListaServicos( sacFachada.listarServicos());
            }
        } catch (PersistenceException pe){
            throw new ServletException ("Problema de persistencia, " + pe.getMessage());
        }


        String functionName = request.getParameter(SACHandler.FUNCTION_ID);
        String res = null;
        Object handler;
        if (functionName.equals(currentFunction)) {
            handler = currentImplementer;
        } else {
            handler = functionImplementers.get(functionName);
        }
        if (handler != null) {
            res = ((SACHandler) handler).processRequest(request, response, sacFachada);
            this.currentFunction = functionName;
            this.currentImplementer = (SACHandler) handler;
        } else {
            System.out.println("Nao conseguiu obter o handler " + functionName);
        }
        return res;
    }

    /**
     * Metodo auxiliar para preencher alguns campos do formulario, atraves do Bean.
     * Ele preenche as selecoes de doencas e tipos de servico.
     *
     * @ param bean Bean que deve ter esses campos preenchidos.
     */
    private void preencherForm (CadastroPFBean bean) {
        List listaDoencas = getListaDoencas();
        List listaserv = getListaServicos();

        String[] todas_doencas = new String[listaDoencas.size()];
        String[] todas_doencasId = new String[listaDoencas.size()];
        for (int i = 0; i < listaDoencas.size(); i++) {
          Doenca d = (Doenca) listaDoencas.get(i);
          todas_doencas[i] = d.getNome();
          todas_doencasId[i] = d.getId().getLongValue() +"";
          System.out.println("Doenca = "+ d.getNome() + " OID = " + d.getId().getLongValue() );
        }

        String[] todas_servicos = new String[listaserv.size()];
          System.out.println("Numero de servicos = " +       listaserv.size());
        todas_servicos = (String[])listaserv.toArray(todas_servicos);

        bean.setTodas_doencas(todas_doencas);
        bean.setTodas_doencasID(todas_doencasId);
        bean.setTodos_servicos(todas_servicos);
    }

    /**
     * Handler para a operacao de cadastro de Pessoa física no sistema.
     */
    private class CadastroPFHandler extends SACHandler {

     /** Constantes que guardam os caminhos dos JSP.
      *  FIXME isso tem que estar num arquivo!!!!!!!!!!!!
      */
      private static final String URL_CADASTRO_PF = "/jsp/cadastroPF.jsp";
      private static final String URL_CADASTRO_OK = "/portal.jsp";

      /**
       * Constantes utilizadas no Request desse Handler.
       */
      private static final String CADASTRO_PF_BEAN_REQUEST = "cadastroPF";

      /** Constantes que definem os nomes dos Inputs do Form.
      */
      private static final String NOME_INPUT = "nome";
      private static final String CPF_INPUT = "cpf";
      private static final String SENHA_INPUT = "senha";
      private static final String ENDERECO_INPUT = "endereco";
      private static final String BAIRRO_INPUT = "bairro";
      private static final String CIDADE_INPUT = "cidade";
      private static final String ESTADO_INPUT = "estado";
      private static final String PAIS_INPUT = "pais";
      private static final String CEP_INPUT = "cep";
      private static final String TELEFONE_INPUT = "telefone";
      private static final String EMAIL_INPUT = "email";
      private static final String SERVICOS_INPUT = "servicos";
      private static final String HISTORICO_INPUT = "historico";
      private static final String CURRICULUM_INPUT = "curriculum";
      private static final String DOENCAS_INPUT = "doencas";

      /** 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 res = URL_CADASTRO_PF;

        PessoaFisica pessoa = null;

        String nome = request.getParameter(NOME_INPUT);
        String cpf  = request.getParameter(CPF_INPUT);
        String senha = request.getParameter(SENHA_INPUT);
        String rua = request.getParameter(ENDERECO_INPUT);
        String bairro = request.getParameter(BAIRRO_INPUT);
        String cidade = request.getParameter(CIDADE_INPUT);
        String estado = request.getParameter(ESTADO_INPUT);
        String pais = request.getParameter(PAIS_INPUT);
        String cep = request.getParameter(CEP_INPUT);
        String telefone = request.getParameter(TELEFONE_INPUT);
        String email = request.getParameter(EMAIL_INPUT);
        String [] servicos = request.getParameterValues(SERVICOS_INPUT);
        String historico = request.getParameter(HISTORICO_INPUT);
        String [] doencas = request.getParameterValues(DOENCAS_INPUT);
        doencas =  (doencas != null)? doencas : new String[0];

        CadastroPFBean cadastroPF = new CadastroPFBean();
        cadastroPF.setNome(nome);
        cadastroPF.setCpf(cpf);
        cadastroPF.setSenha(senha);
        cadastroPF.setEndereco(rua);
        cadastroPF.setBairro(bairro);
        cadastroPF.setCidade(cidade);
        cadastroPF.setEstado(estado);
        cadastroPF.setPais(pais);
        cadastroPF.setCep(cep);
        cadastroPF.setTelefone(telefone);
        cadastroPF.setEmail(email);
        cadastroPF.setServicos(  Arrays.asList(servicos));
        cadastroPF.setHistorico(historico);
        cadastroPF.setDoencas( Arrays.asList(doencas));
        cadastroPF.setOperation(OPERACAO_CADASTRO);

        preencherForm(cadastroPF);

        try {

          /**
           * Caso algum campo obrigatorio seja deixado em branco
           *
           */
          if(nome.equals("") || cpf.equals("") || senha.equals("") || rua.equals("") ||
             bairro.equals("") || cidade.equals("") || pais.equals("") || cep.equals("") ||
             telefone.equals("") ) {

             	cadastroPF.setPreenchimento("Os campos com * são de preenchimento obrigatório!");

           	/** Insere bean no request*/
           	request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);

                /** Define a página de resposta */

          } else {
	          // Validando CPF...
	          Endereco endereco = new Endereco(rua, bairro, cidade, estado, pais,
	                                          cep, telefone);

	          Vector listaDoencas = new Vector();
                  for(int i=0; i<doencas.length; i++) {
                    listaDoencas.add( sac.doenca.DBDoenca.getInstancia().procurar( new sac.persistencia.OID (  Long.valueOf( doencas[i]).longValue() )));
                  }
                  Vector listaServicos = new Vector();
                  for(int i=0; i<doencas.length; i++) {
                    listaServicos.add(servicos[i]);
                  }
                  pessoa = new PessoaFisica(nome, cpf, senha, endereco, listaDoencas);

	          pessoa.setDescricaoAtividades(historico);
                  pessoa.setTiposServicos(listaServicos);

	          // FIX ME!!!!
	          // Como receber o arquivo pelo request?
	          // pessoa.setCurriculo();
	          fachada.cadastraPessoaFisica(pessoa);
                  res = URL_CADASTRO_OK;
	  }

        /**
         * Caso o CPF seja invalido...
         */
        } catch (CPFInvalidoException cpfie) {

            cadastroPF.setErroCpf("CPF Inexistente!");

            /** Insere o Bean no request. */
            request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
        /**
         * Caso a senha seja invalida...
         */
        } catch (SenhaInvalidaException sie) {
            cadastroPF.setErroSenha("Senha inválida. Deve possuir mais de 4 caracteres.");
            request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
        } catch (ItemJaCadastradoException ijce) {
            cadastroPF.setErroCadastro("Pessoa com CPF já registrada no sistema!");
            request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
        } catch (PersistenceException pe) {
            cadastroPF.setErroPersistencia("Problemas na conexão com o BD");
            request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
        } catch ( sac.doenca.DoencaNaoCadastradaException dnce) {
            dnce.printStackTrace();
        } catch (InvalidArgumentException iae) {
            // nao vai acontecer
            iae.printStackTrace();
        } catch (NullArgumentException nae) {
            // nao vai acontecer
            nae.printStackTrace();
        }

      return res;
      }

    }

    /**
     * Handler para a operacao de alteracao de Pessoa Fisica no Sistema
     */
    private class AlteracaoPFHandler extends SACHandler {

       /** Constantes que guardam os caminhos dos JSP.
        *  FIXME isso tem que estar num arquivo!!!!!!!!!!!!
        */
        private static final String URL_CADASTRO_PF = "/jsp/cadastroPF.jsp";
        private static final String URL_CADASTRO_OK = "/portal.jsp";

        /**
        Constantes utilizadas no Request desse Handler.*/
        private static final String CADASTRO_PF_BEAN_REQUEST = "cadastroPF";

        /** Constantes que definem os nomes dos Inputs do Form.
        */
        private static final String NOME_INPUT = "nome";
        private static final String CPF_INPUT = "cpf";
        private static final String SENHA_INPUT = "senha";
        private static final String ENDERECO_INPUT = "endereco";
        private static final String BAIRRO_INPUT = "bairro";
        private static final String CIDADE_INPUT = "cidade";
        private static final String ESTADO_INPUT = "estado";
        private static final String PAIS_INPUT = "pais";
        private static final String CEP_INPUT = "cep";
        private static final String TELEFONE_INPUT = "telefone";
        private static final String EMAIL_INPUT = "email";
        private static final String SERVICOS_INPUT = "servicos";
        private static final String HISTORICO_INPUT = "historico";
        private static final String CURRICULUM_INPUT = "curriculum";
        private static final String DOENCAS_INPUT = "doencas";

       /** 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 res = URL_CADASTRO_PF;

          PessoaFisica pessoa = null;
          PessoaFisica pessoaAntiga = null;

          String nome = request.getParameter(NOME_INPUT);
          String cpf  = request.getParameter(CPF_INPUT);
          String rua = request.getParameter(ENDERECO_INPUT);
          String bairro = request.getParameter(BAIRRO_INPUT);
          String cidade = request.getParameter(CIDADE_INPUT);
          String estado = request.getParameter(ESTADO_INPUT);
          String pais = request.getParameter(PAIS_INPUT);
          String cep = request.getParameter(CEP_INPUT);
          String telefone = request.getParameter(TELEFONE_INPUT);
          String email = request.getParameter(EMAIL_INPUT);
          String [] servicos = request.getParameterValues(SERVICOS_INPUT);
          String historico = request.getParameter(HISTORICO_INPUT);
          String [] doencas = request.getParameterValues(DOENCAS_INPUT);
          doencas =  (doencas != null)? doencas : new String[0];

          CadastroPFBean cadastroPF = new CadastroPFBean();
          cadastroPF.setNome(nome);
          cadastroPF.setCpf(cpf);
          cadastroPF.setEndereco(rua);
          cadastroPF.setBairro(bairro);
          cadastroPF.setCidade(cidade);
          cadastroPF.setEstado(estado);
          cadastroPF.setPais(pais);
          cadastroPF.setCep(cep);
          cadastroPF.setTelefone(telefone);
          cadastroPF.setEmail(email);
          cadastroPF.setServicos(Arrays.asList(servicos));
          cadastroPF.setHistorico(historico);
          cadastroPF.setDoencas( Arrays.asList(doencas));
          cadastroPF.setOperation(OPERACAO_ALTERACAO);

          preencherForm(cadastroPF);

          try {

            OID oid = (OID) request.getSession().getAttribute(this.OID_SESSION);
            pessoaAntiga = (PessoaFisica) fachada.procuraUsuario(oid, UsuarioComum.STATUS_PESSOA_FISICA);

            /**
            * Caso algum campo obrigatorio seja deixado em branco
            */
            if(nome.equals("") || rua.equals("") ||
              bairro.equals("") || cidade.equals("") || pais.equals("") || cep.equals("") ||
              telefone.equals("") ) {

             	cadastroPF.setPreenchimento("Os campos com * são de preenchimento obrigatório!");

           	/** Insere bean no request*/
           	request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);

            } else {
	          Endereco endereco = new Endereco(rua, bairro, cidade, estado, pais,
	                                          cep, telefone);
                  endereco.setEmail(email);

	          Vector listaDoencas = new Vector();
                  for(int i=0; i<doencas.length; i++) {
                    listaDoencas.add( sac.doenca.DBDoenca.getInstancia().procurar( new sac.persistencia.OID (  Long.valueOf( doencas[i]).longValue() )));
                  }
                  Vector listaServicos = new Vector();
                  for(int i=0; i<doencas.length; i++) {
                    listaServicos.add(servicos[i]);
                  }
                  pessoa = new PessoaFisica(nome, cpf, pessoaAntiga.getSenha(), endereco, listaDoencas);

	          pessoa.setDescricaoAtividades(historico);
                  pessoa.setTiposServicos(listaServicos);

                  fachada.alteraPessoa(pessoaAntiga, pessoa);
                  res = URL_CADASTRO_OK;
            } /**
               * Caso a senha seja invalida...
               */
          } catch (SenhaInvalidaException sie) {
              cadastroPF.setErroSenha("Senha inválida. Deve possuir mais de 4 caracteres.");
              request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
          } catch (ItemNaoCadastradoException ijce) {
              // Nao dave acontecer...
              cadastroPF.setErroCadastro("Pessoa com CPF não registrada no sistema!");
              request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
          } catch (PersistenceException pe) {
              cadastroPF.setErroPersistencia("Problemas na conexão com o BD");
              request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
          /*} catch ( sac.doenca.DoencaNaoCadastradaException dnce) {
              dnce.printStackTrace();*/
          } catch (InvalidArgumentException iae) {
              // nao vai acontecer
              iae.printStackTrace();
          } catch (NullArgumentException nae) {
              // nao vai acontecer
              nae.printStackTrace();
          }

          return res;
        }

    }

    private class PreencherCadPFHandler extends SACHandler {
      private static final String URL_CADASTRO_PF = "/jsp/cadastroPF.jsp";
      private static final String CADASTRO_PF_BEAN_REQUEST = "cadastroPF";

      /** 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 {

          CadastroPFBean cadastroPF = new CadastroPFBean();
          preencherForm(cadastroPF);
          cadastroPF.setOperation(OPERACAO_CADASTRO);
          request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
          return URL_CADASTRO_PF;
      }
    }

    /**
     * Handler para preencher todo o menu de cadastro a partir da pessoa física
     * que está logada. Precisa ser chamado antes de ser chamada a operação de Alteração,
     * para que o formulário apareça todo preenchido.
     *
     * FIX ME!!!!
     * Como saber realmente se a PF está logada? é preciso fazer essa verificação?
     */
    private class PreencherTodoCadPFHandler extends SACHandler {
      private static final String URL_CADASTRO_PF = "/jsp/cadastroPF.jsp";
      private static final String CADASTRO_PF_BEAN_REQUEST = "cadastroPF";

      /** 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 {

        CadastroPFBean cadastroPF = new CadastroPFBean();

        try {
            OID oid = (OID) request.getSession().getAttribute(this.OID_SESSION);
            PessoaFisica pessoa = (PessoaFisica) fachada.procuraUsuario(oid, UsuarioComum.STATUS_PESSOA_FISICA);
            cadastroPF = new CadastroPFBean(pessoa);
            preencherForm(cadastroPF);
            cadastroPF.setOperation(OPERACAO_ALTERACAO);
            request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);

          } catch (PersistenceException pe) {
            cadastroPF.setErroPersistencia("Problemas na conexão com o BD");
            request.setAttribute(CADASTRO_PF_BEAN_REQUEST, cadastroPF);
          } catch (ItemNaoCadastradoException ince) {
            // Vai acontecer?
            // Ver comentario da classe...
            ince.printStackTrace();
          } catch (InvalidArgumentException iae) {
            iae.printStackTrace();
          }

          return URL_CADASTRO_PF;
      }
    }

}