/*
 * Copyright
 *   2008 axYus - www.axyus.com
 *   2008 C.Bosquet - charles.bosquet@axyus.com
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package fr.gouv.finances.dgfip.xemelios.web.utils;

import java.util.Iterator;
import java.util.List;
import java.util.Stack;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionMapping;

/**
 * @author Thomas Antalick
 */
public class FilAriane {

  private Stack<ElementAriane> pile;

  public FilAriane() {
    pile = new Stack();
  }

  public void setEcranActuel(HttpServletRequest request, ActionMapping mapping, ElementAriane.Niveau niveau, String titreEcran) {
    setEcranActuel(request, mapping, niveau, titreEcran, null);
  }

  public void setEcranActuel(HttpServletRequest request,ActionMapping mapping, ElementAriane.Niveau niveau, String titreEcran, String attributsDeSessionAPurger[]) {
    ElementAriane arianeBean = new ElementAriane();
    arianeBean.setNiveau(niveau);
    
    arianeBean.setTitre(titreEcran);
    for (int i = 0; attributsDeSessionAPurger != null && i < attributsDeSessionAPurger.length; i++) {
      arianeBean.doitPurgerEnSession(attributsDeSessionAPurger[i]);
    }
    setEcranActuel(arianeBean, request, mapping);
  }

  /**
   * Définit l'écran actuel
   */
  private void setEcranActuel(ElementAriane element, HttpServletRequest request, ActionMapping mapping) {
    ElementAriane eltCourant = null;
    
    if (!StringUtils.isBlank(mapping.getParameter())) {
      element.doitSauver(mapping.getParameter());
    }
    
    // Tout d'abord on reconstitue l'url de l'écran pour revenir dessus avec tous les paramétres nécessaires
    if (element.getUrl() == null || element.getUrl().length() == 0) {
      element.setUrl(buildUrl(element, request));
    }
    // Si son niveau niveau est définit en dur
    if (element.getNiveau() != ElementAriane.Niveau.NOEUD_NIV_N) {
      if (!pile.isEmpty()) {
        eltCourant = (ElementAriane) pile.lastElement();
      }
      // On dépile tous les éléments qui se situent aprés son niveau
      while (pile.size() > element.getNiveau().getValue()) {
        /* si l'écran actuellement parcouru dans la pile est différent
         * de l'écran qu'on est entrain de définir, on purge ses données de la session.*/
        if (!element.getTitre().equals(eltCourant.getTitre())) {
          purgerSession(eltCourant.getListeAPurger(), request);
        }
        pile.pop();
        if (!pile.isEmpty()) {
          eltCourant = (ElementAriane) pile.lastElement();
        }
      }
    } // Si son niveau n'est pas définit en dur
    else {
      if (!pile.isEmpty()) {

        Iterator it = pile.iterator();
        int i = 1;
        while (it.hasNext()) {
          ElementAriane elt = (ElementAriane) it.next();

          if (element.getTitre().equals(elt.getTitre())) {
            int taillePile = pile.size();
            for (int j = taillePile; j >= i; j--) {
              if (j != i) {
                purgerSession(elt.getListeAPurger(), request);
              }

              pile.pop();
            }
            break;
          }
          i++;
        }
      }
    }

    pile.push(element);
  }

  public void purgeSession(int index, HttpServletRequest request) {
    ElementAriane eltCourant = null;
    if (!pile.isEmpty()) {
      eltCourant = (ElementAriane) pile.lastElement();
    }
    while (pile.size() > index + 1) {
      purgerSession(eltCourant.getListeAPurger(), request);
      pile.pop();
      eltCourant = (ElementAriane) pile.lastElement();
    }
  }

  /**
   * Retourne l'url de l'élément de la pile dont on a fournit l'index, et dépile tous ceux qui
   * se trouvent au dessus en purgeant leurs données en session
   */
  public String getUrlElementAriane(int index, HttpServletRequest request) {
    purgeSession(index, request);
    return pile.get(index).getUrl();
  }

  /**
   * Récupére l'url compléte de l'écran afin de pouvoir y accéder sans perdre aucune données
   * nécessaires à son affichage
   */
  private String buildUrl(ElementAriane element, HttpServletRequest request) {
    String url = request.getRequestURL().toString();
    String queryString = "";
    // On mémorise tous les parametres qu'on a décider de sauvegarder pour l'écran en cours (grace
    // à la méthode doitSauver(String) de la classe ElementArianeBean)
    queryString += "filAriane=true";
    List paramASauver = element.getListeParamASauver();
    Iterator i = paramASauver.iterator();
    while (i.hasNext()) {
      if (queryString.length() > 0) {
        queryString += "&";
      }
      String nomParam = i.next().toString();
      String valeurParam = null;
      if (request.getParameter(nomParam) != null) {
        valeurParam = request.getParameter(nomParam);
        queryString += nomParam + "=" + valeurParam;
      } else if (request.getAttribute(nomParam) != null) {
        valeurParam = request.getAttribute(nomParam).toString();
        queryString += nomParam + "=" + valeurParam;
      }
    }
    return url + (queryString.length() > 0 ? "?" + queryString : "");
  }

  /**
   * Retourne le code html pour afficher le fil d'ariane
   */
  public String getStrFilAriane(HttpServletRequest request) {
    String fil = "";
    boolean premier = true;
    int i = 0;
    Iterator it = pile.iterator();
    while (it.hasNext()) {
      ElementAriane eltCourant = (ElementAriane) it.next();
      fil += (premier ? "" : " &gt; ") + (pile.size() != i + 1 && eltCourant.isCliquable() ? "<a href='" + request.getContextPath() + "/commun/filAriane.do?goto=" + String.valueOf(i) + "' class='filAriane'>" + eltCourant.getTitre() + "</a>" : eltCourant.getTitre());
      premier = false;
      i++;
    }
    return fil;
  }

  public int getSize() {
    return pile.size();
  }

  public static void purgerSession(List listeAPurger, HttpServletRequest request) {
    HttpSession session = request.getSession(false);

    if (session != null) {
      Iterator i = listeAPurger.iterator();
      while (i.hasNext()) {
        session.removeAttribute((String) i.next());
      }
    }
  }
}
