// lab04.cpp  (c) 2000 adolfo@di-mare.com

/** \file  lab04.cpp
    \brief Ejemplo de una clase para años bisiestos.

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

    - Cálculo del año bisiesto:
    - Dado un año "A", "A" es bisiesto si es múltiplo de 4, exceptuando
      los múltiplos de 100, que no son bisiestos, a menos que sean
      múltiplos de 400.

    Por ejemplo:

    - 1998 no es múltiplo de 4, por lo tanto, no es bisiesto.
    - 1900 es múltiplo de 4 y de 100, pero no es múltiplo de 400,
           entonces no es bisiesto.
    - 2000 sí es bisiesto.
    - 1988 sí es bisiesto.

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


#include <iostream>
#include <bool.h>

/// Almaceno el año.
class bisiesto {
private:
    int m_ano;   ///< Añoc
    int m_dias;  ///< Calcula de antemano la cantidad de días del año.
public:
    // constructores
    bisiesto() : m_ano(0), m_dias(366) {} ///< Constructor de vector
    bisiesto(bisiesto& o) : m_ano(o.m_ano), m_dias(o.m_dias) {} ///< Constructor de copia
    /// Constructor para una año específico.
    bisiesto(int a) : m_ano(a) {m_dias = (es_bisiesto() ? 366 : 365);}

    /// Copia.
    bisiesto& operator=(bisiesto& o) { m_ano = o.m_ano; m_dias = o.m_dias; return *this; }

    // métodos
    bool es_bisiesto(); ///< Retorna \c true cuando el año es bisiesto.
    int  dias_del_mes(int mes);
    int  dias() { return m_dias; }

    // convertidor
    operator int() { return m_ano; }

    friend istream& operator>> (istream& s, bisiesto& a);
}; // bisiesto


/// Retorna "true" cuando el año sí es bisiesto.
bool bisiesto::es_bisiesto() {
    bool 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;
} // bisiesto::es_bisiesto()


/// Retorna la cantidad de días que tiene el i-ésimo mes del año.
/// - Los meses se numeran desde \c 1 hasta \c 12.
/// - Enero es \c 1 ... Diciembre es \c 12.
int bisiesto::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;
} // dias_del_mes()

/// Permite grabar en el flujo de salida \c "s" el valor de \c "A".
istream& operator>> (istream& s, bisiesto& A) {
    s >> A.m_ano;
    A.m_dias = (A.es_bisiesto() ? 366 : 365);

    return s;
} // operator>> ()

/// Programa principal.
int main() {
    bisiesto A = 1492;

    while (A != 0) {
        cout << endl << "Escriba un año (0 para terminar): ";
        cin  >> A;   // operator>>(cin, A);

        cout << "El año " << A;
        if (!A.es_bisiesto()) {
            cout << " NO";
        }
        else {
        }
        cout << " es bisiesto";
    }
    return 0;
} // main()

// EOF: lab04.cpp