package org.tela_botanica.client;

import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Rafraichissable;
import org.tela_botanica.client.modeles.objets.Utilisateur;
import org.tela_botanica.client.observation.ObservationMediateur;
import org.tela_botanica.client.vues.EtatConnexionVue;
import org.tela_botanica.client.vues.FenetreLicenceVue;
import org.tela_botanica.client.vues.FormulaireDeConnexionVue;
import org.tela_botanica.client.vues.ListeUtilisateurAdminVue;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.gwtext.client.core.EventCallback;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Ext;
import com.gwtext.client.core.ExtElement;
import com.gwtext.client.widgets.BoxComponent;
import com.gwtext.client.widgets.Container;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.TabPanel;
import com.gwtext.client.widgets.Tool;
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
import com.gwtext.client.widgets.event.TabPanelListenerAdapter;
import com.gwtext.client.widgets.layout.FitLayout;
import com.gwtext.client.widgets.layout.RowLayout;
import com.gwtext.client.widgets.layout.RowLayoutData;

/**
 * Mediateur gérant les interactions entre vues et les echanges de données
 * C'est un singleton. 
 * @author david delon 
 *
 */

public class CarnetEnLigneMediateur implements Rafraichissable {
	
	
	/**
	 * booleen qui verifie l'unicite de l'instance
	 */
	private static boolean estInstancie = false ;

	/**
	 * pointeur vers le médiateur lui même (pour le pattern singleton)
	 */
	private static CarnetEnLigneMediateur thisMediateur = null ;  
		
	/**
	 * modele de données
	 */
	
	private  CarnetEnLigneModele carnetEnLigneModele=null;

	
	/**
	 * panneau principal de l'application "Carnet en ligne"
	 */

	private Panel panneauPrincipalCarnetEnLigne= null ;
	
	
	
	/**
	 * panneau a onglet pour les observation et les images
	 */ 
	
	
	private com.gwtext.client.widgets.TabPanel ongletsObservationsImages=null;
	
	
	/**
	 * Indicateur d'etat de la connexion utilisateur
	 */
	
	private EtatConnexionVue etatConnexionVue=null;
	
	
	/**
	 * Texte d'invite connexion  
	 */
	private final String texteDeconnexion="Utilisez ce carnet en ligne pour saisir vos observations, <u>identifiez-vous</u> pour les transmettre à Tela Botanica"; 

	/**
	 * Boolean indiquant un essai de connexion
	 */
	
	private boolean tentativeConnection=false;
	
	/**
	 * Booleen indique que la licence a été acceptée
	 */
	private boolean licenceUtilisateurAcceptee = false;
	

	/**
	 *  Formulaire de connexion (lazy instantiation)
	 *  
	 */
	
	private FormulaireDeConnexionVue formulaireDeConnexionVue=null;
	
	/**
	 * 
	 */
	private Panel bandeau = null ;
	
	private Panel panneauAdmin = null ;
	
	Tool cacherPanneau = null ;
	
	private FenetreLicenceVue fenetreAcceptationLicence = null;
	
	/**
	 * Mediateur Gestion des images
	 */
	
	private ImageMediateur imageMediateur=null;
	
	/**
	 * Mediateur Gestion des observations
	 */
	
	private ObservationMediateur observationMediateur=null;
	
	/**
	 * Utilisateur en cours
	 */

		
	private Utilisateur utilisateur=null; 
	

	
	public static CarnetEnLigneMediateur Instance()
	{
			if(!estInstancie || thisMediateur==null)
			{
				estInstancie = true ;
				thisMediateur = new CarnetEnLigneMediateur() ;
			}
			
			return thisMediateur ;
			
	}
	
	
	/**
	 * constructeur privé (on accède a la classe par la méthode getInstance
	 */
	
	private CarnetEnLigneMediateur() {
	
		
		panneauPrincipalCarnetEnLigne = new Panel("Carnet en ligne");
		
//		Disposition 
		
		panneauPrincipalCarnetEnLigne.setLayout(new RowLayout());

		
		// Pourrait etre fait plus loin ... 
		carnetEnLigneModele=CarnetEnLigneModele.Instance();
		
		
		bandeau = new Panel();
		bandeau.setId("x-up-bandeau") ;
		etatConnexionVue=new EtatConnexionVue(this);
		etatConnexionVue.setLayout(new FitLayout()) ;
		
		// Le panneau à onglet qui contient les 2 applications Observation et Images 
		
		ongletsObservationsImages = new TabPanel();
		
		panneauPrincipalCarnetEnLigne.add(etatConnexionVue,new RowLayoutData(16));
		
		panneauAdmin = new Panel();
		panneauAdmin.setId("panneau_admin");
		panneauPrincipalCarnetEnLigne.add(panneauAdmin, new RowLayoutData(16));
		panneauAdmin.setBorder(false);
		panneauAdmin.hide();
		
		panneauPrincipalCarnetEnLigne.add(ongletsObservationsImages,new RowLayoutData());
		//panneauPrincipalCarnetEnLigne.addTool(cacherPanneau) ;
		
	
		
		// On ajoute les applications 		
		observationMediateur = ObservationMediateur.Instance(this);
		imageMediateur= ImageMediateur.Instance(this);
		
		if(!GWT.isScript()) {
			//temp dd viewport desactive ajout de cette  ligne
			getPanneauPrincipalCarnetEnLigne().setHeight(Window.getClientHeight()) ;
		}
		
		panneauPrincipalCarnetEnLigne.addListener(new ContainerListenerAdapter() {

			@Override
			public void onResize(BoxComponent component, int adjWidth,
					int adjHeight, int rawWidth, int rawHeight) {
				CarnetEnLigneMediateur.fireResize();
				observationMediateur.redimensionnerPanneaux(adjHeight, adjWidth);
				
			}
		});
		
		ongletsObservationsImages.addListener(new TabPanelListenerAdapter() {
									
			@Override
			public void onTabChange(TabPanel source, Panel tab) {
				if(tab.equals(imageMediateur.getPanneauPrincipalImage())) {
					
					Timer t = new Timer() {
						
						@Override
						public void run() {
							imageMediateur.obtenirNombreMiniListeObservations();
							imageMediateur.rafraichirToutesVues();
						}
					};
					
					t.schedule(150);
				}
			}
		});
		
		//	on ajoute les panneaux  principaux des applications au panneau à onglets
		ongletsObservationsImages.add(observationMediateur.getPanneauPrincipalObservation());
		ongletsObservationsImages.add(imageMediateur.getPanneauPrincipalImage());
	}
	
	
	public void getEtatUtilisateur() { 
							
		
		carnetEnLigneModele.getEtatUtilisateur(this); 
				
		
	}


	// Methode publiques
	
	
	
	/**
	 * Recherche Identifiant utilisateur en cours et etat de connection
	 * @return Utilisateur
	 */
	
	
	public Utilisateur getUtilisateur() {
		return utilisateur;
	}

	/**
	 * Deconnecte l'utilisateur passe en parametre
	 */
    public void deconnecterUtilisateur() {
    	
    	licenceUtilisateurAcceptee = false;
    	
    	// TODO: vider proprement toutes les vues (méthode à voir)
		carnetEnLigneModele.deconnecterUtilisateur(this, Utilisateur.getInstance().getIdentifiantUtilisateurConsulte());
		
		observationMediateur.deconnecterUtilisateur() ;
		imageMediateur.deconnecterUtilisateur();
		
		panneauAdmin.setVisible(false);
	}

	public void connecterUtilisateur(String login, String password) {
	
		tentativeConnection=true;
		carnetEnLigneModele.connecterUtilisateur(this, login, password); 
		
	}


	
	/**
	 *  Affichage etat de la connexion
	 */
	
	
	private void afficheEtatConnexion() {
		
		if (!utilisateur.isIdentifie()) {
			   etatConnexionVue.setEtat("",false);
		}
		else {
			if(utilisateur.isAdmin()) {
		    	afficherLienAdmin();
				panneauAdmin.setVisible(true);
		    } else {
		    	cacherLienAdmin();
		    }
			
		    etatConnexionVue.setEtat(Utilisateur.getInstance().getLoginUtilisateurConsulte(),true);
		      
		}
		
	}
	
	private void afficherFenetreAcceptationLicence()  {
		
		fenetreAcceptationLicence = new FenetreLicenceVue(this);
		
		// On le positionne à peu près au milieu de l'écran
		int left = (Window.getClientWidth() - 512) / 2;
		int top = (Window.getClientHeight() - 256) / 5;
		  
		fenetreAcceptationLicence.setPosition(left, top);
		fenetreAcceptationLicence.setHeight(350);
		fenetreAcceptationLicence.setWidth(550);
		fenetreAcceptationLicence.setModal(true);
		fenetreAcceptationLicence.show();
	}

	
	/**
	 * 
	 * Affichage boite de connexion
	 *
	 */
	
	
	public void afficherDialogueConnexion() {
		
		  if (formulaireDeConnexionVue==null) { 
			  formulaireDeConnexionVue= new FormulaireDeConnexionVue(this);
		  }
		  
		  // On le positionne à peu près au milieu de l'écran
		  int left = (Window.getClientWidth() - 512) / 2;
		  int top = (Window.getClientHeight() - 256) / 2;
		  
		  formulaireDeConnexionVue.setPopupPosition(left, top);
		  formulaireDeConnexionVue.show();
		
	}

	public Panel getPanneauPrincipalCarnetEnLigne() {
		return panneauPrincipalCarnetEnLigne;
	}

	@Override
	public void rafraichir(Object nouvelleDonnees, boolean repandreRaffraichissement) {

			if (nouvelleDonnees instanceof Utilisateur) {
							      
				utilisateur = (Utilisateur) nouvelleDonnees;
				
				if ((tentativeConnection) && !utilisateur.isIdentifie()) {
					
					panneauAdmin.setVisible(false);
					formulaireDeConnexionVue.afficherMessageAlerte();
				}
				else {
					if ((tentativeConnection) && utilisateur.isIdentifie()) {
						afficherLienAdmin();
						formulaireDeConnexionVue.cacher();
					}
				}
				
				if(utilisateur.isIdentifie() && !utilisateur.getLicenceAcceptee()) {
					afficherFenetreAcceptationLicence();
				} else {
					
				  if(tentativeConnection && utilisateur.isIdentifie() && observationMediateur.listeAvoirObservations() && !utilisateur.isAdmin()) {
					  if(Window.confirm("Voulez vous importer vos observations déjà saisies dans votre compte une fois connecté ?")) {
						  observationMediateur.setImporterObservationsAnonymes(true);
					  }
				  }
				
				  afficheEtatConnexion();
				  // On lance l'affichage des observations
				  observationMediateur.connecterUtilisateur();
				  imageMediateur.connecterUtilisateur();
					
				}
			}
			
			if(nouvelleDonnees instanceof String) {
				
				String evenement = (String)nouvelleDonnees;
				
				if(evenement.equals("licence_acceptee")) {
					licenceUtilisateurAcceptee = true;
					accepterLicenceUtilisateur();
				} else {
					if(utilisateur.isIdentifie()) {
						deconnecterUtilisateur();
						return;
					}
				}
				
				if(observationMediateur.listeAvoirObservations() && !utilisateur.isAdmin()) {
					if(Window.confirm("Voulez vous importer vos observations déjà saisies dans votre compte une fois connecté ?")) {
					  observationMediateur.setImporterObservationsAnonymes(true);
					}
				}
				
				afficheEtatConnexion();
				observationMediateur.connecterUtilisateur();
				imageMediateur.connecterUtilisateur();
				
				fenetreAcceptationLicence.close();
			}
	}
	
	private void accepterLicenceUtilisateur() {
		utilisateur.setLicenceAcceptee(true);
		carnetEnLigneModele.accepterLicenceUtilisateur(Utilisateur.getInstance().getIdentifiantUtilisateurConsulte());
	}

	public void afficherListeUtilisateurs() {
		
		ListeUtilisateurAdminVue listeUtilisateur = new ListeUtilisateurAdminVue(this) ;
		listeUtilisateur.show(Ext.get("LienChangerUtilisateur").getDOM());
		listeUtilisateur.focusChampUtilisateur();
		
	}
	
	public void afficherLienAdmin() {

		String labelAdmin = "<div id=\"lienAdmin\">Vous consultez les données de "+Utilisateur.getInstance().getLoginUtilisateurConsulte()+"  <a id=\"LienChangerUtilisateur\" href=\"#\">Changer d'utilisateur</a></div>" ;
		panneauAdmin.setHtml(labelAdmin);
		
		ExtElement lienChangerUt = Ext.get("LienChangerUtilisateur");
		if(lienChangerUt != null) 
		{	
			lienChangerUt.removeAllListeners();
			lienChangerUt.addListener("click", new EventCallback() {

				@Override
				public void execute(EventObject e) {
					afficherListeUtilisateurs();
				}				
			});
		}
		else
		{
			panneauAdmin.addListener(new ContainerListenerAdapter() 
			{
				@Override
				public void onAfterLayout(Container c) 
				{
					ExtElement lienChangerUt = Ext.get("LienChangerUtilisateur");
					lienChangerUt.removeAllListeners();
					lienChangerUt.addListener("click", new EventCallback() {

						@Override
						public void execute(EventObject e) {
							afficherListeUtilisateurs();
						}
						
					});
				}
			});
		}
	}
	
	public void cacherLienAdmin() { 
		panneauAdmin.hide();
	}
	
	public void changerIdentite(String idNouvelleIdentite, String loginNouvelleIdentite) {
		Utilisateur.getInstance().setUtilisateurConsulte(idNouvelleIdentite, loginNouvelleIdentite);
		afficherLienAdmin();
		observationMediateur.connecterUtilisateur();
		imageMediateur.connecterUtilisateur();
	}

	public void obtenirListeUtilisateurs(String rech, Rafraichissable r) {
		carnetEnLigneModele.obtenirListeUtilisateur(r,rech,Utilisateur.getInstance().getIdentifiantUtilisateurConnecte());
	}

	public void donneesImagesVersObs(Object o) {
		observationMediateur.donneesExterieures(o);
	}
	
	public void donneesObsVersImages(Object o) {
		imageMediateur.donneesExterieures(o);
	}
	
	public void obtenirListeObservations(Rafraichissable r) {
		observationMediateur.obtenirCacheObservation(r) ;
	}


	public static native void fireResize() /*-{
		 $wnd.Ext.EventManager.fireResize();
	}-*/;

}