import java.util.ArrayList;
import java.util.Collections;

import javax.swing.JOptionPane;

/** Esta clase creará o modificará un Usuario
 */
public class EditorUsuario
{
    private Usuario usuario;
    private Datos datos = new Datos();
    private static ArrayList < Ramo > malla = new ArrayList < Ramo > ();
    private ArrayList < ArrayList > semestres = new ArrayList < ArrayList > ();
    private ArrayList < ArrayList > semestres1 = new ArrayList < ArrayList > ();

    /** Constructor del Objeto EditorUsuario.
     */
    public EditorUsuario()
    {
    }

    /** Crea un nuevo usuario
     * @param nombre Es el nombre del usuario.
     * @param carrera Es el codigo de la carrera.
     */
    public void creaUsuario(String nombre, int carrera)
    {
        usuario = new Usuario(nombre, carrera);
        malla = datos.getMalla(Integer.toString(carrera));
        semestres = null;
        semestres = new ArrayList < ArrayList > ();
        ordenarSemestres();
        datos.setCargado(false);
    }

    /** Carga un usuario
     * @param nombre Es el nombre del usuario que hay que cargar.
     */
    public void cargarUsuario(String nombre)
    {
        usuario = datos.cargarUsuario(nombre);
        malla = datos.getMalla(Integer.toString(usuario.getCarrera()));
        for(int i = 0; i < usuario.getRamosPasados().size(); i++)
            for(int j = 0; j < malla.size(); j++)
                if(usuario.getRamosPasados().get(i).equals(malla.get(j).getSigla()))
                {
                    malla.get(j).setRamoPasado(true);
                    break;
                }
        semestres = null;
        semestres = new ArrayList < ArrayList > ();
        ordenarSemestres();
    }

    /** Guarda el usuario en disco.
     */
    public void guardarUsuario()
    {
    		datos.guardarUsuario(usuario);
    }

    /** Agrega o quita el ramo de la lista de ramos pasados.
     * @param ramo Es el ramo que hay que agregar o quitar.
     */
    public void setRamo(String ramo)
    {
        for(int i = 0; i < malla.size(); i++)
            if ( malla.get(i).getSigla().equals(ramo) )
                malla.get(i).setRamoPasado(!malla.get(i).isPasado());

        if(usuario.getRamosPasados().indexOf(ramo) >= 0)
            usuario.setRamoPendiente(ramo);
        else
            usuario.setRamoPasado(ramo);
    }

    /** Actualiza el valor del coigo de carrera.
     * @param carrera Es el nuevo codigo de carrera.
     */
    public void setCarrera(int carrera)
    {
        usuario.setCarrera(carrera);
    }

    /** Actualiza el nombre.
     * @param nombre Es el nuevo nombre.
     */
    public void setNombre(String nombre)
    {
        usuario.setNombre(nombre);
    }

    /** Ordena los Ramos de la malla para separarlos por semestre.
     */
    private void ordenarSemestres()
    {
        ArrayList < Celda > semestre = new ArrayList < Celda > ();
        int s = 0;
        int i = 1;
        while (true)
        {
            semestre.clear();
            for (int j=0; j<malla.size(); j++)
            {
                if (i == malla.get(j).getSemester())
                {
                    semestre.add( new Celda( malla.get(j).isPasado(), 
                        malla.get(j).getSigla() ) );
                    s++;
                }
            }
            semestres.add((ArrayList)semestre.clone());
            i++;
            if (s == malla.size())
                break;
        }
    }

    /** Retorna el arreglo de ramos ordenados por semestre que se desea.
     * @param b Es el diferenciador entre recibir.
     * @return El Array de semestres solicitado.
     */
    
    public ArrayList < ArrayList > getSemestres (boolean b)
    {
        if (b)
        	return semestres;
        else
        	return semestres1;
    }

    /** La cantidad de ramos en un arreglo.
     * @param b determina el tipo de arreglo en cuestion.
     * @return El numero pedido.
     */ 
    public int getNumeroRamos (boolean b)
    {
        if (b)
        	return malla.size();
        else
        	return malla.size()-usuario.getRamosPasados().size();
    }
    
    /** Retorna el codigo de una carrera.
     * @return Es el codigo de la carrera.
     */
    public int getCarrera(){
    	return usuario.getCarrera();
    }

    /** Setea los pesos correspondientes a cada ramo de la malla.
     */
    private void setPesos()
    {
        ArrayList <String> prereq;
        Collections.sort(malla);

        for(int i = 0; i < malla.size(); i++)
        {
            prereq = malla.get(i).getPre();
            if(prereq.size() == 0)
                continue;
            else
                for(int j = i; j < malla.size(); j++)
                   for(int k = 0; k < prereq.size(); k++)
                       if(prereq.get(k).equals(malla.get(j).getSigla()))
                       {
                           malla.get(j).setWeight(1 + malla.get(i).getWeight());
                           break;
                       }
        }
    }

    /** Ordena los ramos de acuerdo a sus pesos respectivos,
     * importancia dentro de la carrera y peso academico que desea el usuario.
     * @param sem_actual es el semestre que esta cursando el usuario.
     * @param max_cred corresponde a la maxima cantidad de cretitos requerida
     * por el usuario.
     * @param max_ram corresponde a la maxima cantidad de ramos requerida
     * por el usuario.
     */ 
    public void ordenarSemestresporPeso(int sem_actual, int max_cred, int max_ram)
    {
        setPesos();
        Collections.sort(malla, new OrdenaRamos());
        ArrayList < Celda > semestre = new ArrayList < Celda > ();
        semestres1.clear();
        ArrayList < String > ramos_pasados = new ArrayList < String > ();
        for(int i = 0; i < usuario.getRamosPasados().size(); i++)
            ramos_pasados.add( usuario.getRamosPasados().get(i) );
        

        ArrayList < Ramo > malla_aux = new ArrayList < Ramo > ();
        for(int i = 0; i < malla.size(); i++)
            malla_aux.add(malla.get(i).clone()); 

        int sem = sem_actual;
        while (malla_aux.size() > 0)
        {
            semestre.clear();
            int creditos = 0, numramos = 0;
            for (int i=0; i<malla_aux.size(); i++)
            {
                if ( ramos_pasados.contains( malla_aux.get(i).getSigla() ) )
                {
                    malla_aux.remove(i);
                    i--;
                    continue;
                }
                if ( malla_aux.get(i).checkPosibility(ramos_pasados, sem) 
                    && (creditos + malla_aux.get(i).getCredits() <= max_cred) 
                    && (numramos < max_ram) )
                {
                    semestre.add(new Celda(false, malla_aux.get(i).getSigla()) );
                    creditos += malla_aux.get(i).getCredits();
                    numramos++;
                    malla_aux.remove(i);
                    i--;
                }
            }
            for(int i = 0; i < semestre.size(); i++)
                ramos_pasados.add( semestre.get(i).toString() );
            semestres1.add((ArrayList)semestre.clone());
            sem = (sem % 2) + 1;
        }
    }

    /** Retorna un objeto ramo que coincida con el string dado.
     * @param r Ramo solicitado.
     * @return Ramo solicitado.
     */
	public static Ramo getRamo(String r){
		 for (int i=0;i<malla.size();i++){
			 if (((Ramo)malla.get(i)).getSigla().equals(r)){
				 return (Ramo)malla.get(i);
			 }
		 }
		 return null;
	 }
}
