package siprp.pagina;

import java.io.*;
import java.lang.reflect.Array;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.util.*;

import org.apache.velocity.*;
import org.apache.velocity.app.*;

import com.evolute.utils.*;
import com.evolute.utils.arrays.*;
import com.evolute.utils.db.*;
import com.evolute.utils.sql.*;
import com.evolute.utils.strings.*;

public class siprpServlet extends HttpServlet
	implements GlobalConstants
{
    // MSG
    public static final String msgErroNoUser = "Tem+de+especificar+um+utilizador.";
    public static final String msgErroAuthFail = "Utilizador+inexistente+e/ou+Password+errada.";
    public static final String msgErroBd = "Erro+na+liga&ccedil;&atiolde;o+&agrave;+base+de+dados.";
    public static final String msgGenericError = "Erro";
    public static final String msgListaEmpresas = "Empresas";
    public static final String msgAcessoNegado = "Acesso+Negado.";
    public static final String msgLinkFormatError ="URL+inv&aacute;lido.";
    public static final String msgLogin = "Login";
    public static final String msgNovaPasswordErrada="Erro+ao+criar+a+nova+password,+nova+password+inv&aacute;lida.";
    public static final String msgButtonNotSuported = "funcionalidade+ainda+n&atilde;o+suportada.";
    public static final String msgSessionTimeout = "Por+raz&otilde;es+de+seguran&ccedil;a+o+tempo+da+sua+sess&atilde;o+expirou<br>" 
													+ "Por+favor+efectue+novamente+o+seu+login.<br>";
    
    // Templates - Nomes e valores
    //public static final String loginTemplate = "login.html";

	public static final String indexTemplate = "index.html";
	public static final String authenticatedUserTemplate = "user.html";
	public static final String authenticatedUserPrintTemplate = "user_print.html";
	public static final String errorTemplate = "frame_erro.html";
	public static final String innerErrorTemplate = "erro.html";

    public static final String mainTemplate = "main.html";
    //public static final String criticalErrorTemplate = "critical.html";
    public static final String templateVector1 ="v1";
    public static final String templateVector2 ="v2";
    public static final String templateVector3 ="v3";
    public static final String templateUserRole ="userRole";
    public static final String msgTemplate ="msg";
    public static final String templateQuery ="query";
    public static final String buttonPressedTemplate ="buttonPressed";
    
    // Query Strings , usadas para na template do velocity saber o que mostar
	public static final String queryStringErro = "erro";  
    public static final String queryStringEmpresas = "empresas";  
    public static final String queryStringEstabelecimentos="estabelecimentos";
    public static final String queryStringTrabalhadores ="trabalhadores";
    public static final String queryStringTrabalhador ="trabalhador";
    
    //Botoes, saber qual o botao escholido, campo value dos forms
    public static final String botaoLogin = "Entrar";
    public static final String botaoMarcarProximoExame = "Marcar Exame";
    
    // Var da Session
    public static final String sessionUser="user";
    public static final String sessionUserRole="userRole";
    public static final String sessionPassword="password";
    public static final String sessionEmpresaId="empresaId";
    public static final String sessionEstabelecimentoId="estabelecimentoId";
    public static final String sessionTrabalhadorId="trabalhadorId";
    public static final String sessionCompanyName = "sessionCompanyName";
    public static final String sessionCompanyEmail = "sessionCompanyEmail";
    public static final int sessionTimeout = 3600; // segundos
    
    public static final String servletName="siprpWeb";
    public static final String superUserRole="manager";
    
//    // BD
//    public static final String bdHost = "127.0.0.1";
//    public static final String bdPort = "5436";
//    public static final String bdUsername = "siprp";
//    public static final String bdPassword = "";
//    public static final String bdDriver = "org.postgresql.Driver";
//    public static final String bdUrl = "jdbc:postgresql://" + bdHost + ":" + bdPort + "/siprp";
    
    public static final String bdEmpresaIdRef = "id"; // campo que contem id da empresa
    public static final String bdEmpresaNomeRef = "designacao_social"; // campo que contem nome da empresa
    public static final String bdEstIdRef = "id"; // campo que contem nome do estabelecimento
    public static final String bdEstNomeRef = "nome"; // campo que contem nome do estabelecimento
    public static final String bdTrabIdRef = "id"; // campo que contem id do trabalhador
    public static final String bdTrabNomeRef = "nome"; // campo que contem nome do trabalhador
    public static final String bdNullString = ""; // String a mostrar quando o campo lido da BD é null
    public static final String bdEmailEmpresa = "email"; // campo que contem email da empresa
    
    protected static ServletContext CONTEXT;
	
    // Arrays 
    public static final String[][] trabalhadorDescFields = new String [][]
    { // nome que o user ve, nome do campo na tabela
                {"Nome",                "nome"},
                {"Nº",                  "numero_mecanografico",},
                {"\u00DAltimo Exame",        "ultimo_exame"},
                {"Realizado",           "realizado"},
                {"Pr\u00F3ximo Exame",       "proximo_exame"},
                {"\u00DAltima Consulta",     "ultima_consulta"},
                {"Realizada",           "realizada"},
                {"Pr\u00F3xima Consulta",    "proxima_consulta"}
    };     
               
    public void init()
    {
        
        try {
            CONTEXT = this.getServletContext();
            String TEMPLATE_DIR = this.getServletContext().getRealPath( "/" ) + "html/";
System.out.println( "DIR: " + TEMPLATE_DIR );
            Properties props = new Properties();
            props.setProperty( "file.resource.loader.path", TEMPLATE_DIR );
            Velocity.init( props );
            Class.forName(bdDriver);
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
    }
    
    public void doGet( HttpServletRequest req, HttpServletResponse res )
		throws IOException
    {   
        String queryString = req.getQueryString();
        String backUri = req.getRequestURI();
        ServletOutputStream out = res.getOutputStream();
        res.setContentType( "text/html" );
        try
        {
System.out.println( "query: " + queryString );			
            HttpSession session = req.getSession(true);
            session.setMaxInactiveInterval(sessionTimeout);
            
            if ( queryString == null ) // Reload, 1º vez, etc ...
            {
                session.invalidate();
                out.println( mergeTemplate ( msgLogin, indexTemplate ) ) ;
            }
            else if ( session.isNew() && !( queryString.indexOf(queryStringErro) == 0 ) ) // session timeout
            {
                session.invalidate();
				out.println( mergeTemplate( msgGenericError , errorTemplate ) );
//				doErro(queryString, out);
            }
            else if ( queryString.equals(queryStringEmpresas) ) // Listar Empresas
            {
                new doGetListaEmpresas(req,res);
            }
			else if ( queryString.indexOf(queryStringErro) == 0 ) // Listar Empresas
            {
//	System.out.println( "entrou" );
                doErro(queryString, out);
            }
            else // interpretar query string
            {
                String empresa = null, estabelecimento=null, trabalhador=null;
				String query = null;
                int checkInt;
                
                StringTokenizer sToken = new StringTokenizer(queryString,"/") ;
                empresa = sToken.nextToken(); // empresa ID
                checkInt = Integer.parseInt(empresa); // check int, NumberFormatException
                
                if (sToken.hasMoreElements())
                {
                    estabelecimento = sToken.nextToken(); // estabelecimento ID
                    checkInt = Integer.parseInt(estabelecimento); // check int, NumberFormatException
                    if (sToken.hasMoreElements())
                    {
                        trabalhador = sToken.nextToken(); // trabalhador ID
						try
						{
	                        checkInt = Integer.parseInt(trabalhador); // check int, NumberFormatException
						}
						catch( NumberFormatException nfex )
						{
							query = trabalhador;
							if( query.indexOf( "trabalhadores_tudo" ) != 0 && query.indexOf( "trabalhadores_pendentes" ) != 0 &&
								query.indexOf( "_print" ) == -1 )
							{
								throw nfex;
							}
						}
                    }  
                }
                
				if ( estabelecimento == null ) // empresa query
                {
                    session.setAttribute(sessionEmpresaId, empresa); // update HTTP Session
                    
                    new doGetListaEstabelecimentos(req,res);
                    
                    //out.println( mergeTemplate ( empresa, loginTemplate ) ) ;
                }
                else if ( trabalhador == null || query != null ) // estabelecimento  query
                {
                    session.setAttribute(sessionEmpresaId, empresa);  // update HTTP Session
                    session.setAttribute(sessionEstabelecimentoId, estabelecimento);
                    
                    new doGetListaTrabalhadores(req,res, query);
                    
                    //out.println( mergeTemplate ( " chama oGetListaTrabalhadores", loginTemplate ) ) ;
                }
                else // trabalhador query
                {
                    session.setAttribute(sessionEmpresaId, empresa);  // update HTTP Session
                    session.setAttribute(sessionEstabelecimentoId, estabelecimento);
                    session.setAttribute(sessionTrabalhadorId, trabalhador);
                    
                    new doGetTrabalhador(req,res);
                    
                    //out.println( mergeTemplate ( trabalhador, loginTemplate ) ) ;
                }
            }
        }
        catch ( NumberFormatException e )  // argumentos invalidos
        {
            e.printStackTrace();
            out.println( mergeTemplate( msgLinkFormatError, backUri, errorTemplate) );
        }
        catch ( IllegalStateException e ) // session timeout
        {
            e.printStackTrace();
            out.println( mergeTemplate(msgSessionTimeout, errorTemplate) );
        }
        catch ( Exception e )
        {
            e.printStackTrace();
//            out.println( mergeTemplate( msgGenericError , backUri, errorTemplate ) );
			out.println( mergeTemplate( msgGenericError , errorTemplate ) );
        }
//		System.out.println( "fim - " + queryString + " bu " + backUri  );
    }
        
    public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws IOException
    {
        ServletOutputStream out = res.getOutputStream();
        //StringBuffer dbQuery;
        //ResultSet2DArray rs;
        //Connection con = null ;
        //Statement stmt = null ;
        //String user, userRole, password;
        String buttonPressed = req.getParameter("form");
        
        try
        {
            if ( buttonPressed.equals(botaoLogin))
            {
                new doPostLogin(req,res);
            }
            else
            {
                out.println( mergeTemplate( msgButtonNotSuported, errorTemplate) );
            }
        }
        /*catch ( SQLException e )
        {
            e.printStackTrace();
            out.println( mergeTemplate( msgErroBd , criticalErrorTemplate) );
        }*/
        catch ( IllegalStateException e ) // session timeout
        {
            e.printStackTrace();
            out.println( mergeTemplate(msgSessionTimeout, errorTemplate) );
        }
        catch ( Exception e )
        {
            e.printStackTrace();
            out.println( mergeTemplate( msgGenericError , errorTemplate) );
        }
    }

    
    public String mergeTemplate( HashMap values, String template )
    {
        VelocityContext context = new VelocityContext();
        StringWriter output = new StringWriter();
        
        try
        {
		for( Iterator i = values.keySet().iterator(); i.hasNext(); )
		{
			String key = ( String ) i.next();
			context.put ( key, values.get( key ) ) ;
		}
		
            Velocity.mergeTemplate(template, Velocity.ENCODING_DEFAULT, context, output );
            return output.toString();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
    
    
    
    public String mergeTemplate (String msg, String template ) // #1
    {
        VelocityContext context = new VelocityContext();
        StringWriter output = new StringWriter();
        
        try
        {
            context.put ( msgTemplate , msg ) ;
            Velocity.mergeTemplate(template, Velocity.ENCODING_DEFAULT, context, output );
            return output.toString();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public String mergeTemplate (String msg, String userRole, String template ) // #1
    {
        
        VelocityContext context = new VelocityContext();
        StringWriter output = new StringWriter();
        
        try
        {
            context.put ( msgTemplate , msg ) ;
            context.put ( templateUserRole, userRole);
            Velocity.mergeTemplate(template, Velocity.ENCODING_DEFAULT, context, output );
            return output.toString();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public String mergeTemplate ( String msg, String userRole, String querySelected, Vector vector1, Vector vector2, Vector vector3, String template ) // #2
    {
        
        VelocityContext context = new VelocityContext();
        StringWriter output = new StringWriter();
        
        try
        {
            context.put ( msgTemplate , msg ) ;
            context.put ( templateUserRole, userRole);
            context.put ( templateQuery, querySelected );
            context.put ( templateVector1,vector1);
            context.put ( templateVector2,vector2);
            context.put ( templateVector3,vector3);
            Velocity.mergeTemplate(template, Velocity.ENCODING_DEFAULT, context, output );
            return output.toString();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }

    public void destroy()
    {
    }
    
    public void handleSessionTimeout(HttpServletResponse res, String template)
    throws IOException
    {
        ServletOutputStream out = res.getOutputStream();
        try
        {
            out.println( mergeTemplate( msgSessionTimeout, template) );
        }
        catch ( Exception e )
        {
            e.printStackTrace();
            
        }
    }
    
    public boolean verificaEstabelecimento(Connection con, java.lang.String empresaId, java.lang.String estabelecimentoId)
    // verifica se o establecimento pertence à empresa
    {
        //Connection con = null ;
        Statement stmt = null ;
        Virtual2DArray rs;
        String query;
        try
        {
            //con = DriverManager.getConnection( bdUrl, bdUsername, bdPassword ); 
            query = "SELECT empresa_id FROM estabelecimentos where id='"+estabelecimentoId+"'";
			if( con != null )
			{
				stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
				rs = new ResultSet2DArray( stmt.executeQuery( query ) );
			}
			else
			{
				rs = getExecuter().executeQuery( new Select( query ) );
			}
            String temp=""+rs.get(0,0); // converter de int para String
			if( con != null )
			{
				stmt.close();
			}
            if ( empresaId.equals(temp) ) // estabelecimento pertence à empresa
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        return false;
    }
    
    public boolean verificaTrabalhador(Connection con, java.lang.String estabelecimentoId, java.lang.String trabalhadorId)
    // verifica se o trabalhador pertence ao estabelecimento
    {
        //Connection con = null ;
        Statement stmt = null ;
        ResultSet2DArray rs;
        StringBuffer dbQuery;
        try
        {
            //con = DriverManager.getConnection( bdUrl, bdUsername, bdPassword );   
            dbQuery = new StringBuffer();
            dbQuery.append(  "SELECT estabelecimento_id FROM trabalhadores where id='"+trabalhadorId+"'");
            stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            rs = new ResultSet2DArray( stmt.executeQuery( dbQuery.toString()) );
            String temp=""+rs.get(0,0); // converter de int para String
            stmt.close();
            if ( estabelecimentoId.equals(temp) ) // estabelecimento pertence à empresa
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        return false;
    }
    
    public void closeSqlCon(Connection con)
    {
        try
        {
            if (con != null ) con.close();
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        
    }
    
    public String emailEmpresa(Connection con, String empresaId)
    {
        Statement stmt = null ;
        ResultSet2DArray rs;
        StringBuffer dbQuery;
        String returnString;
        
        try
        {
            dbQuery = new StringBuffer();
            dbQuery.append( "SELECT email FROM empresas, contactos "
							+ "WHERE empresas.id ='"+empresaId+"' AND empresas.contacto_1 = contactos.id");
			stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            rs = new ResultSet2DArray( stmt.executeQuery( dbQuery.toString()) );
	    if( rs.columnLength() > 0 )
	    {
		    returnString = (String)rs.get(0,0);
		    stmt.close();
		    return returnString;
	    }
	    else
	    {
		    return null;
	    }
        }
	catch ( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public String nomeEmpresa(Connection con, String empresaId)
    {
        Statement stmt = null ;
        Virtual2DArray rs;
        String returnString;
        
        try
        {
			String query = "SELECT designacao_social FROM empresas WHERE id ='"+empresaId+"'";
			if( con != null )
			{
				stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
				rs = new ResultSet2DArray( stmt.executeQuery( query ) );
			}
			else
			{
				rs = getExecuter().executeQuery( new Select( query ) );
			}
	    if( rs.columnLength() > 0 )
	    {
		    returnString = (String)rs.get(0,0);
			if( con != null )
			{
				stmt.close();
			}
		    return returnString;
	    }
	    else
	    {
		    return null;
	    }
        }
		catch ( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public String nomeEstabelecimento(Connection con, java.lang.String estabelecimentoId)
    {
        Statement stmt = null ;
        Virtual2DArray rs;
        StringBuffer dbQuery;
        String returnString;
        
        try
        {
            String query = "SELECT nome FROM estabelecimentos WHERE id ='"+estabelecimentoId+"'";
			if( con != null )
			{
				stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
				rs = new ResultSet2DArray( stmt.executeQuery( query ) );
			}
			else
			{
				rs = getExecuter().executeQuery( new Select( query ) );
			}
	    if( rs.columnLength() > 0 )
	    {
		    returnString = (String)rs.get(0,0);
			if( con != null )
			{
				stmt.close();
			}
		    return returnString;
	    }
	    else
	    {
		    return null;
	    }
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public String nomeTrabalhador(Connection con, java.lang.String trabalhadorId)
    {
        Statement stmt = null ;
        ResultSet2DArray rs;
        StringBuffer dbQuery;
        String returnString;
        
        try
        {
            dbQuery = new StringBuffer();
            dbQuery.append( "SELECT nome FROM trabalhadores where id='"+trabalhadorId+"'");
            stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            rs = new ResultSet2DArray( stmt.executeQuery( dbQuery.toString()) );
	    if( rs.columnLength() > 0 )
	    {
		    returnString = (String)rs.get(0,0);
		    stmt.close();
		    return returnString;
	    }
	    else
	    {
		    return null;
	    }
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        return null;
    }
	
	public void doErro( String queryString, ServletOutputStream out )
		throws Exception
	{
		String split[] = queryString.split( "=" );
		String err;
		if( split.length > 1 )
		{
			err = split[ 1 ];
		}
		else
		{
			err = "Erro";
		}
		err = err.replace( '+', ' ' );
		out.println( mergeTemplate( err, innerErrorTemplate) );
	}
	
	protected Executer getExecuter()
		throws Exception
	{
		ServletContext context = CONTEXT;
		DBManager dbm = ( DBManager ) context.getAttribute( Singleton.DEFAULT_DBMANAGER );
		if( dbm == null )
		{
			dbm = new JDBCManager( bdLocalUrl, bdLocalUsername, bdLocalPassword , 500, 499, 1, null );
			context.setAttribute( Singleton.DEFAULT_DBMANAGER, dbm );
		}
		return dbm.getSharedExecuter();
	}
}

