import java.applet.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import java.awt.Font.*;

/**
 * Calendrier Grégorien débutant le 15 septembre 1582
 * @author Bertrand MAINZ
 * @version 1
 */


 // <applet code=Calendrier.class width=300 height=280> </applet>

public class Calendrier extends Applet {
	Button bannee_precedant;			//	Définition des Boutons
	Button bannee_suivant;				//
	Button bmois_precedant;				//
	Button bmois_suivant;				//
	int annee_actuel;				//	Définition des variables
	int mois_actuel;
	int jour_actuel;
	int nom_jour_actuel;				//
	int annee_choisi;				//
	int mois_choisi;				//
	Graphics affichage;				//	Définition de l'objet de type graphique
	Calendar aujourdhui;				//	Définition de l'objet de type calendar
	int jour_annee_actuel;
	Image buffer;
	/** Méthode principale */
	public void init () {

		setBackground(Color.white);			// Couleur de l'arrière plan
		setForeground(Color.blue);			// Couleur de l'avant plan
		buffer = createImage(300,280);
		aujourdhui = Calendar.getInstance ();		// Création d'une instance de la classe Calendar
		mois_actuel = aujourdhui.get(Calendar.MONTH);	// affectation de la valeur du mois en cours
		annee_actuel = aujourdhui.get(Calendar.YEAR);	// affectation de la valeur de l'année en cours
		jour_actuel = aujourdhui.get(Calendar.DAY_OF_MONTH);
		nom_jour_actuel = aujourdhui.get(Calendar.DAY_OF_WEEK);
		jour_annee_actuel = aujourdhui.get(Calendar.DAY_OF_YEAR);
		annee_choisi = annee_actuel;
		mois_choisi = mois_actuel;

		bannee_precedant = new Button ("Année -");				// Ajout du bouton année -
		bannee_precedant.addActionListener (new ActionListener() {		// Ajout d'un écouteur,
			public void actionPerformed(ActionEvent E) {			// associé à un évenement
		  		if (annee_choisi<=1583 && mois_choisi <=9)	{
		  			annee_choisi = 1582;
		  			mois_choisi=9;
		  		}
		  			else annee_choisi=annee_choisi - 1;
		  		repaint ();						// sert pour le réaffichage des nouvelles valeurs
		  	}
		} ) ;

		bannee_suivant = new Button ("Année +");				//Ajout du bouton année +
		bannee_suivant.addActionListener (new ActionListener() {
			public void actionPerformed(ActionEvent E) {
		  		annee_choisi = annee_choisi + 1;
		  		repaint ();
		  	}
		} ) ;

		bmois_precedant = new Button ("Mois -");				//Ajout du bouton mois -
		bmois_precedant.addActionListener (new ActionListener() {
			public void actionPerformed(ActionEvent E) {
		  		if (annee_choisi<=1582) {
		  			if (mois_choisi <=9) {mois_choisi =9; annee_choisi= 1582;}
		  			else {mois_choisi = mois_choisi-1 ; annee_choisi= 1582;}
		  		}
		  		else {
		  			if (mois_choisi==0) {mois_choisi =11; annee_choisi= annee_choisi - 1;}
		  			else {mois_choisi = mois_choisi - 1;}
		  		}
		  		repaint ();
		  	}
		} ) ;

		bmois_suivant = new Button ("Mois +");					//Ajout du bouton mois +
		bmois_suivant.addActionListener (new ActionListener() {
			public void actionPerformed(ActionEvent E) {
		  		if (mois_choisi == 11) { mois_choisi = 0; annee_choisi = annee_choisi + 1 ;}
		  		else {mois_choisi = mois_choisi + 1;}
		  		repaint ();
		  	}
		} ) ;

		//Affichage des composants graphiques
			add (bannee_precedant);		// Ajout du bouton année -
			add (bmois_precedant);		// Ajout du bouton mois -
			add (bmois_suivant);		// Ajout du bouton mois +
			add (bannee_suivant);		// Ajout du bouton année +
                repaint();
}

	public void paint(Graphics g) {
		update(g);
	}

	/** Méthode paint */
	public void update (Graphics g1){
		Font police;
		Graphics g = buffer.getGraphics();

		g.setColor(Color.white);
		g.fillRect(0,0,300,280);
		g.setColor(Color.blue);
		int L;		// Déclaration de la variable servant à définir la largeur de l'applet
		L=300;		// Affectation d'une valeur à cette variable (presque tout est calculé en fonction de celle-ci)

		String nomJour2 [] ={"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
		String mois[] = {"JANVIER","FEVRIER","MARS","AVRIL","MAI","JUIN","JUILLET","AOUT","SEPTEMBRE",
				"OCTOBRE","NOVEMBRE","DECEMBRE"};  // tableau permettant d'aller chercher les chaînes correspondant aux mois
		police = new Font ("Serif",Font.BOLD,16);
		g.setFont(police);
		g.drawString (mois[mois_choisi] + "   " + Integer.toString(annee_choisi),L/3,60);	// Affichage du mois est de l'année choisis
		police = new Font ("Serif",Font.PLAIN,12);
		g.setFont(police);
		g.drawRect((L/10),75,(8*L/10),20);				// Cadre pour les jours de la semaine

		String nomJour [] = {" L"," M"," M"," J"," V"," S"," D"};	// tableau permettant d'aller chercher les chaînes correspondant aux jours de la semaine

			for (int i=0; i<7; i++)					//Affichage des jours de la semaine
			g.drawString (nomJour[i],((L/10)+((i+1)*(L/10))),90);

		g.drawRect (L/10,100,(8*L/10),150);	// Cadre contenant les jours du mois

		// affichage des valeurs pour le mois choisi


		int col = premierJourDuMois (mois_choisi,annee_choisi);
		int lign =1;
		int nb;

		if ( annee_choisi == 1582 && mois_choisi == 9) {
			col = 5;
			lign = 3;
		}


		int Xpos = (L/10) + col*(L/10); 	//position du 1er chiffre en x
		int Ypos = 110 + lign*20;		//position du 1er chiffre en y

		nb = nbJour(mois_choisi, annee_choisi);

		if (annee_choisi == 1582 && mois_choisi == 9) {
			for (int i=15; i<=nb ; i++){
				g.setColor(Color.gray);

				if ( (estJourFerie (i, mois_choisi, annee_choisi)) == true ) g.setColor(Color.red);
				if ( col == 7) g.setColor(Color.red);

				if ( i<10)
				g.drawString (Integer.toString(i),Xpos+1,Ypos);
				else g.drawString (Integer.toString(i),Xpos,Ypos);




				if (col == 7) { col = 1; lign = lign +1;}
				else col = col + 1;

				Xpos= (L/10)+ col*(L/10);
				Ypos= 110 + lign*20;
			}
		}
		else {
			for (int i=1; i<= nb; i++){
				g.setColor(Color.gray);

	//*********Dessin de l'encadrement du jour courant*********************************************

				if ( (i==aujourdhui.get(Calendar.DAY_OF_MONTH)) && (mois_choisi == aujourdhui.get(Calendar.MONTH)) && (annee_choisi == aujourdhui.get(Calendar.YEAR)) ) {
					g.setColor(Color.red);
					g.drawRect(Xpos-3,Ypos-15,20,20);
					g.setColor(Color.gray);
				}
	//*********************************************************************************************


				if ( (estJourFerie (i, mois_choisi, annee_choisi)) == true ) g.setColor(Color.red);
				if ( col == 7) g.setColor(Color.red);

				if ( i<10)
				g.drawString (Integer.toString(i),Xpos+4,Ypos);
				else g.drawString (Integer.toString(i),Xpos,Ypos);

				if (col == 7) { col = 1; lign = lign +1;}
				else col = col + 1;

				Xpos= (L/10)+ col*(L/10);
				Ypos= 110 + lign*20;
			}
		}
	//**********Calcul et affichage des infos du jour****************

	g.setColor(Color.darkGray);
	g.drawString ( nomJour2[nom_jour_actuel-1] + " " + jour_actuel + " " + mois[mois_actuel] + " " + Integer.toString(annee_actuel),30,270);
	g.drawString ( "Jour: " + Integer.toString(jour_annee_actuel),30,290);

	g1.drawImage(buffer,0,0,300,280,null);

	}
//----------------------------------------------------------------------------------------------------
	/** Calcul du nombre de jour dans le mois en prenant en compte les années bissextiles
	 *  @param mmm mois dont on veut le nombre de jours
	 *  @param aaa année dont on veut le nombre de jours
	 *  @return le nombre de jour dans le mois
	 */
	public int nbJour (int mmm,int aaa) {

	  if ( mmm == 0 ||  mmm == 2 ||  mmm == 4 ||  mmm == 6 ||  mmm == 7 ||
	       mmm == 9 ||  mmm == 11) return 31;

	  if (mmm == 1) {
	  	if ((aaa % 4 == 0 && aaa % 100 != 0) || aaa % 400 == 0) return 29;
	  	else return 28;
	  }

	  else return 30;

	}
//-----------------------------------------------------------------------------------------------------
	/** Calcul la position du premier jour du mois dans la semaine
	 *  @param m mois dont on veut la position du premier jour
	 *  @param a année dont on veut la position du premier jour du mois
	 *  @return la position du jour dans la semaine;  1:lundi 2:mardi 3:mercredi 4:jeudi 5:vendredi 6:samedi 7:dimanche
	 */

	public int jourJulien(int j, int m, int a ) {
	// Calcul du jour "Julien"
		int tmp1,tmp2, tmp3,tmp4,tmp5;
		if (m > 2) {
			tmp1 = m - 3;
			tmp2 = a;
		} else {
			tmp1 = m + 9;
			tmp2 = a - 1;
		}
		tmp3 = tmp2 / 100;
		tmp4 = tmp2 % 100;
		tmp5 = j;
		return ((146097 * tmp3) / 4 + (1461 * tmp4) / 4 +
		(153 * tmp1 + 2) / 5 + tmp5 + 1721119);
	}

	public int premierJourDuMois (int m,int a){
		int TJour[] = {7,1,2,3,4,5,6};
		int numjour =  (jourJulien(1, m+1, a )+1)  % 7;
		return TJour[numjour];
	}
//------------------Calcul des jour fériés-------------------------------------------------------------
	/** Calcul les jours fériés fixes et mobiles
	 *  @param jj jour
	 *  @param mm mois
	 *  @param aa année
	 *  @return true=jour férié , false=jour non férié
	 */
	public boolean estJourFerie (int jj, int mm, int aa) {
		//Jours fixes
		if ( jj == 1 && mm == 0) return true; 	// jour de l'an
		if ( jj == 1 && mm == 4) return true; 	// fête du travail
		if ( jj == 8 && mm == 4) return true; 	// victoire 1945
		if ( jj == 14 && mm == 6) return true; 	// fête nationale
		if ( jj == 15 && mm == 7) return true; 	// assomption
		if ( jj == 11 && mm == 10) return true; // armistice 1918
		if ( jj == 1 && mm == 11) return true; 	// Toussaint
		if ( jj == 25 && mm == 12) return true; // noël

		// Calcul du Jours de Pâques et du Lundi de Pâques


        		int m; int c; int y; int s; int t; int p; int q; int e; int b; int d; int l; int h;int moispaques; int jourpaques;
        		m=(aa) % 19;
       			c=aa/100;
        		y=(aa) % 100;
        		s=c/4;
        		t=(c) % 4;
        		p=(c+8)/25;
        		q=(c-p+1)/3;
        		e=(19*m+c-s-q+15)% 30;
        		b=y/4;
        		d=y % 4;
        		l=(32+(2*t)+(2*b)-e-d) % 7;
        		h=(m+(11*e)+(22*l))/451;
        		moispaques=((e+l-(17*h)+144)/31)-2;
        		jourpaques=((e+l-(17*h)+144) % 31)+2;

        	if ((jj == jourpaques || jj == jourpaques + 1) && mm == moispaques) return true;

		// Calcul du jour de la Pentecôte et du lundi de Pentecôte

			int jourpentecote =1 ;
			int moispentecote =1 ;

			if ( moispaques == 2 ) {
				jourpentecote = 49 - (31 - jourpaques + 30);
				moispentecote = 4;
			}
			if ( moispaques == 3 && jourpaques <= 12) {
				jourpentecote = 49 - (30 - jourpaques);
				moispentecote = 4;
			}
			if ( moispaques == 3 && jourpaques > 12 ) {
				jourpentecote = 49 - (30 - jourpaques + 31);
				moispentecote = 5;
			}

		if ( (jj == jourpentecote || jj == (jourpentecote +1) ) && mm == moispentecote) return true;

		// Calcul du jour de l'Ascension

			int jourAscension =1 ;
			int moisAscension =1 ;
			if ( jourpaques == 22 && moispaques == 2) {
				jourAscension = 30;
				moisAscension = 3;
			}
			if ( jourpaques > 22 && moispaques == 2) {
				jourAscension = 39 - (31 - jourpaques + 30 );
				moisAscension = 4;
			}
			if ( jourpaques <=22 && moispaques == 3) {
				jourAscension = 39 - (30 - jourpaques);
				moisAscension = 4;
			}
			if ( jourpaques > 22 && moispaques == 3){
				jourAscension = 39 - (30 - jourpaques + 31);
				moisAscension = 5;
			}

		if ( jj == jourAscension && mm == moisAscension) return true;


		else return false;

        }




}
