package de.mmt.lorbeerblatt.webservice.util;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import de.mmt.lorbeerblatt.data.Dish;
import de.mmt.lorbeerblatt.data.Mensa;
import de.mmt.lorbeerblatt.data.dao.DishDao;
import de.mmt.lorbeerblatt.data.dao.MensaDao;
import de.mmt.lorbeerblatt.foodfinder.FoodFinder;

/**
 * Uses the FoodFinder component to get the available mensas and current dishes. 
 * Will save those elements in the MensaDAO and DishDAO singletons. Data is refreshed
 * every hour.
 * You can initialize this component by calling new DataBuilder(servletContext).start();
 * 
 * @author Matthias Niederhausen
 */

public class DataBuilder extends Thread
{
private URL stylesheet;
private static Map<String,String> mensaToID = new HashMap<String,String>();
private static String SOURCEURLBASE = "http://www.studentenwerk-dresden.de/mensen/speiseplan/";
private static String PHOTOURLBASE = "http://bilderspeiseplan.studentenwerk-dresden.de/";

{
mensaToID.put("Neue Mensa","m8");
mensaToID.put("Alte Mensa","m18");
mensaToID.put("Mensa Reichenbachstraße","m9");
mensaToID.put("Mensologie","m5");
mensaToID.put("Mensa Siedepunkt","m6");
mensaToID.put("Mensa Johannstadt","m32");
mensaToID.put("Mensa Zittau","m1");
mensaToID.put("Mensa Palucca Schule","m14");
mensaToID.put("Mensa Görlitz","m15");
}

public DataBuilder(ServletContext context)
  {
   System.setProperty("javax.xml.transform.TransformerFactory","net.sf.saxon.TransformerFactoryImpl");
   
   try
     {
      if (new File(context.getRealPath("WEB-INF/transform.xsl")).exists())
        {
         this.stylesheet = new URL("file","",context.getRealPath("WEB-INF/transform.xsl"));
        }
      else
        {
         this.stylesheet = FoodFinder.class.getClassLoader().getResource("WebContent/WEB-INF/transform.xsl");
        }
     }
   catch (MalformedURLException e)
     {
      e.printStackTrace();
     }
  }

@Override
public void run()
  {
   while (true)
     {
      System.out.println("Running Scraper...");
      this.runScraper();
      
      try
        {
         sleep(1000*3600);
        }
      catch (InterruptedException e)
        {
         e.printStackTrace();
        }
     }
  }

protected void runScraper()
  {
   FoodFinder ff = new FoodFinder();
   Date today = new Date();
   
   try
     {  
      ff.scrape(new URL("http://www.studentenwerk-dresden.de/mensen/speiseplan/"),this.stylesheet);
      Node doc =  ff.currentDocument;
      
      NodeList mensas = doc.getFirstChild().getChildNodes();
      
      for (int i = 0; i < mensas.getLength(); i++)
        {
         Node mensaNode = mensas.item(i);
         Mensa mensa = new Mensa();
         NamedNodeMap atts = mensaNode.getAttributes();
         mensa.name = atts.getNamedItem("name").getNodeValue();
         
         if (!MensaDao.instance.getModel().containsValue(mensa)) MensaDao.instance.addItem(mensa);
         else
           {
            for (Mensa m:MensaDao.instance.getModel().values())
              {
               if (m.equals(mensa)) mensa = m;
              }
           }
         
         NodeList dishes = mensaNode.getChildNodes();
         
         for (int j = 0; j < dishes.getLength(); j++)
           {
            Node dishNode = dishes.item(j);
            Dish dish = new Dish();
            
            Node ctx = dishNode.getFirstChild();
            
            dish.name = ctx.getTextContent();
            ctx = ctx.getNextSibling();
            dish.sourceUrl = ctx.getTextContent();
            
            GregorianCalendar cal = new GregorianCalendar();
            cal.setTime(today);
            
            if (!dish.sourceUrl.isEmpty())
              {
               String dishId = dish.sourceUrl.substring(8,dish.sourceUrl.indexOf('.'));
   
               // construct photo url for mensas that offer photos
               if (mensaToID.get(mensa.name) != null)
                 {
                  // <mid>/<date>/thumbs/<dishid>.jpg
                  dish.photoUrl = PHOTOURLBASE+mensaToID.get(mensa.name)+"/"+cal.get(Calendar.YEAR)+(cal.get(Calendar.MONTH)+1)+"/thumbs/"+dishId+".jpg";
                 }
               
               // now prepend url base
               dish.sourceUrl = SOURCEURLBASE+dish.sourceUrl;
               
               ctx = ctx.getNextSibling();
               
               try
                 {
                  dish.priceStudent = (ctx.getTextContent() == null)?0:new Integer(ctx.getTextContent().replace(",",""));
                 }
               catch (Exception e)
                 {
                  dish.priceStudent = 0;
                 }
               
               ctx = ctx.getNextSibling();
               
               try
                 {
                  dish.priceEmployee = (ctx.getTextContent() == null)?0:new Integer(ctx.getTextContent().replace(",",""));
                 }
               catch (Exception e)
                 {
                  dish.priceEmployee = 0;
                 }
               
               ctx = ctx.getNextSibling();
               
               while (ctx != null)
                 {
                  // add ingredients...
                  ctx = ctx.getNextSibling();
                 }
                           
               boolean existsYet = false;
               List<Dish> existingDishes = mensa.getDishesForToday();
               
               for (Dish existingDish:existingDishes)
                 {
                  if (existingDish.equals(dish)) existsYet = true;
                 }
               
               if (!existsYet)
                 {
                  mensa.addDishForDay(today,dish);
                  DishDao.instance.addItem(dish);
                 }
              }
           }
        }
     }
   catch (IOException e)
     {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
  }
}