package coreservlets.listeners;

import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

/** Proces nasłuchujący, który śledzi zamówienia
 *  na towary oferowane w ramach oferty dnia.
 *  <P>
 *  Taken from Core Servlets and JavaServer Pages Volume II
 *  from Prentice Hall and Sun Microsystems Press,
 *  http://volume2.coreservlets.com/.
 *  (C) 2007 Marty Hall, Larry Brown, and Yaakov Chaikin;
 *  may be freely used or adapted.
 */
public class DailySpecialWatcher
    implements HttpSessionAttributeListener {
  private static int dailySpecialCount = 0;
  
  /** Jeżeli nazwa dodanego atrybutu odpowiada
   *  jednej z wcześniej zapisanych nazw order-attribute-names I
   *  wartość atrybutu odpowiada jednej z wartości
   *  przechowywanych w daily-special-item-names, wartość licznika
   *  zamówień na ofertę dnia zostaje zwiększona.
   */
  public void attributeAdded(HttpSessionBindingEvent event) {
    checkForSpecials(event, 1);
  }

  /** Jeżeli nazwa usuniętego atrybutu odpowiada
   *  jednej z wcześniej zapisanych nazw order-attribute-names I
   *  wartość atrybutu odpowiada jednej z wartości
   *  przechowywanych w daily-special-item-names, wartość licznika
   *  zamówień na ofertę dnia zostaje zmniejszona.
   */
  public void attributeRemoved(HttpSessionBindingEvent event) {
    checkForSpecials(event, -1);
  }

  /** Jeżeli nazwa zastąpionego atrybutu odpowiada
   *  jednej z wcześniej zapisanych nazw order-attribute-names I
   *  wartość atrybutu odpowiada jednej z wartości
   *  przechowywanych w daily-special-item-names, wartość licznika
   *  zamówień na ofertę dnia zostaje zmniejszona. Warto zauważyć,
   *  że wartością atrybutu jest tutaj wartość dotychczasowa
   *  (czyli wartość zastępowana), zaś metoda attributeAdded
   *  będzie obsługiwać wartość nową (wartość zastępującą).
   */
  public void attributeReplaced(HttpSessionBindingEvent event) {
    checkForSpecials(event, -1);
  }

  /** Sprawdzenie, czy atrybut, który został właśnie dodany
   *  lub zastąpiony odpowiada jednej z nazw w order-attribute-names
   *  I wartość atrybutu odpowiada jednej z wartości przechowywanych
   *  w daily-special-item-names. Jeżeli tak, wartość licznik
   *  zamówień na oferty dnia jest zmieniana (o +1 lub -1).
   */
  private void checkForSpecials(HttpSessionBindingEvent event,
                                int delta) {
    ServletContext context =
      event.getSession().getServletContext();
    ArrayList<String> attributeNames =
      getList(context, "order-attribute-names");
    ArrayList<String> itemNames =
      getList(context, "daily-special-item-names");
    synchronized(attributeNames) {
      for(int i=0; i<attributeNames.size(); i++) {
        String attributeName = attributeNames.get(i);
        for(int j=0; j<itemNames.size(); j++) {
          String itemName = itemNames.get(j);
          if (attributeName.equals(event.getName()) &&
              itemName.equals((String)event.getValue())) {
            dailySpecialCount = dailySpecialCount + delta;
          }
        }
      }
    }
    context.setAttribute("dailySpecialCount",
                         new Integer(dailySpecialCount));
  }

  /** Odczytanie listy order-attribute-names lub
   *  listy daily-special-item-names.
   */
  private ArrayList<String> getList(ServletContext context,
                            String attributeName) {
    ArrayList<String> list =
      (ArrayList)context.getAttribute(attributeName);
    return(list);
  }

  /** Zresetowanie licznika zamówień na oferty dnia.
   *  Operacja jest wykonywana jedynie wówczas,
   *  gdy zmieniony zostanie zakres oferty dnia.
   */
  public static void resetDailySpecialCount() {
    dailySpecialCount = 0;
  }
}
