// Lab04.java (C) 2007 adolfo@di-mare.com

/**
    @(#)Lab04.java 2007
    Ejemplo de una clase para años bisiestos.

    Este programa interactivo recibe un año {@code A} y responde si el año
    es o no bisiesto. Escoja el año {@code A==0} para detener el programa.

    Cálculo del año bisiesto:
    <ul><li> Dado un año {@code "A"}, el año {@code "A"} es bisiesto si es múltiplo de 4,
         exceptuando los múltiplos de {@code 100}, que no son bisiestos, a menos que
         sean múltiplos de {@code 400}. </li></ul>
    Ejemplos:
    <ul><li> {@code 1998} no es múltiplo de {@code 4}, por lo tanto, no es bisiesto. </li>
    <li> {@code 1900} es múltiplo de {@code 4} y de {@code 100}, pero no es múltiplo
         de {@code 400}, entonces no es bisiesto. </li>
    <li> {@code 2000} sí es bisiesto. </li>
    <li> {@code 1988} sí es bisiesto. </li></ul>

    @author Adolfo Di Mare <adolfo@di-mare.com>
*/

import java.io.*; // Clases para leer desde el teclado
import java.lang.System; // Esta siempre la importa Java

/** Clase que contiene el programa principal {@code main()}. */
public class Lab04 {
    /** Programa principal. */
    public static void main( String args[] ) {
        int SIGLOS[] = { 1492 , 2000 , 1999 };
        for ( int i=0; i<SIGLOS.length; i++ ) {
            Bisiesto A = new Bisiesto( 1515 );
            A.set( SIGLOS[i] );
            System.out.print( "\nEl año " + (A.get()) );
            if ( !A.es_bisiesto() ) {
                System.out.print( " NO" );
            }
            System.out.print( " es bisiesto" );
        }
        System.out.println();
        return;
    }
}

/** Estados posible para una variable de tipo {@code Bisiesto}. */
class Estado {
    public final static String SIN_CALCULAR   = "sinCalcular";
    public final static String ES_BISIESTO    = "esBisiesto";
    public final static String NO_ES_BISIESTO = "noEsBisiesto";
   /*  NOTA: Jeliot no permite usar "enum" */
}

/** Almacena el año.
 *  <ul><li> También permite saber si el año es bisiesto. </li>
 *  <li> Retarda el cálculo de año bisiesto hasta que se necesite. </li></ul>
 */
class Bisiesto {
    /** Año almacenado */
    private int m_ano;
    /** Calcula de antemano la cantidad de días del año almacenado. */
    private String m_estado;

    /** Constructor por defecto. */
    public Bisiesto() { m_ano = 0; m_estado = Estado.SIN_CALCULAR; }

    /** Constructor para un año específico. */
    public Bisiesto(int a) { set(a); }

    /** Retorna el año. */
    public int get() { return m_ano; }

    /** Cambia por {@code a} el año almacenado en la instancia. */
    public void set( int a ) {
        m_ano    = a;                   // cambia el año
        m_estado = Estado.SIN_CALCULAR; // luego calcula si es_bisiesto()
    }

    /** Retorna la cantidad de días del año. */
    public int dias() {
        if ( m_estado == Estado.SIN_CALCULAR ) {
            m_estado = ( calcula_bisiesto() ? Estado.ES_BISIESTO : Estado.NO_ES_BISIESTO );
        }
        return ( (m_estado==Estado.ES_BISIESTO) ? 366 : 365 );
    }

    /** Retorna "true" cuando el año sí es bisiesto. */
    public boolean es_bisiesto() {
        return ( dias()==366 );
    }

    /** Retorna "true" cuando el año sí es bisiesto.
      * Esta es la rutina que hace el cálculo la primera vez que se necesita.
      */
    private boolean calcula_bisiesto() {
        boolean es;
        if (m_ano % 100 == 0) {
            if (m_ano % 400 == 0) {  // es = (m_ano % 400 == 0);
                es = true;
            }
            else {
                es = false;
            }
        }
        else {
            es = ((m_ano % 4) == 0);
        }
        return es;
    }

    /** Retorna la cantidad de días que tiene el i-ésimo mes del año.
        <li> Los meses se numeran desde {@code 1} hasta {@code 12}.
        <li> Enero es {@code 1} ... Diciembre es {@code 12}.
    */
    public int dias_del_mes(int mes) {
        int n;
        switch (mes) {
            case 4: case 6:
            case 9: case 11:       n = 30;
                                   break;
            case 1:  case 3:
            case 5:  case 7:
            case 8:
            case 10: case 12:      n = 31;
                                   break;
            case 2:                n = (es_bisiesto() ? 29 : 28);
                                   break;
            default:               n = 0;
                                   break;
        }
        return n;
    }
}

// NOTA: Para ejecutar use el comando:
// > java Lab04
// [en la pantalla de interacciones del DrJava]

// Jeliot:
// - http://cs.joensuu.fi/jeliot/javaws/jeliot.jnlp

// EOF: Lab04.java