package es.upm.dit.gsi.sojason.services.travel;

import jason.asSyntax.Literal;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import es.upm.dit.gsi.sojason.beans.Journey;
import es.upm.dit.gsi.sojason.beans.Perceptable;
import es.upm.dit.gsi.sojason.services.WebServiceConnector;

/**
 * 
 * @author miguel
 *
 */
public class RenfeScrapper implements WebServiceConnector {

	/** 
	 * It contains all the information about the <i>Renfe</i> 
	 * web service URL convenion. 
	 */
	RenfeServiceConvenion queryGenerator;
	
	/**
	 * Constructor
	 * @throws IOException if there is any error while loading the station ids.
	 */
	public RenfeScrapper() throws IOException {
		this.queryGenerator = new RenfeServiceConvenion();
	}
	

	public Collection<Literal> call(String... params) {
		
		if(!validateParams(params)){
			return null;
		}
		try {
			List<Perceptable> schedule = getSchedule  ( params[0].toString(), 
														params[1].toString(), 
														params[2].toString(), 
														params[3].toString(), 
														params[4].toString());
			
			// prepare response
			Collection<Literal> res =  new LinkedList<Literal>();
			for (Perceptable travel : schedule){
				res.addAll(travel.toPercepts());
			}
			return res;
			
		} catch (IOException e) {
//			return CollectionUtils.wrapList("error(io_exception, \"Someio exception ocurr\")");
			return null;
		}
		
	}

	public boolean validateParams(String... params) {
		if(params.length != 5){
			return false;
		}
		return true;
	}
	
	/**
	 * TODO: filter by time
	 * 
	 * 
	 * @param origin
	 * @param destination
	 * @param day
	 * @param month
	 * @param year
	 * @return
	 * @throws IOException 
	 */
	public List<Perceptable> getSchedule (String origin, String destination, 
							  String day, String month, String year) throws IOException {
		
		// The list with the journeys that matches the given criteria
		List<Perceptable> retList = new LinkedList<Perceptable>();
		
		// Get the html
		String queryUrl = "";
		try{
			queryUrl = queryGenerator.generateQuery(origin, destination, day, month, year);
		}
		catch(IllegalArgumentException iae){
			retList.add( queryGenerator.reportParamErrors(origin, destination, day, month, year) );
			return retList;
		}
		Document doc = Jsoup.connect(queryUrl).get();
		
		// Get the rows of the schedule table
		Elements rows = doc.select("table#row > tbody > tr");
		// Each row has the information of a different journey
		for (Element row : rows) {
			Elements cells = row.getElementsByTag("td");
			if(cells.size() > 2){
				
				// get and fill the journey information
				Journey journey = new Journey();
				journey.setOrigin(origin);
				journey.setDestination(destination);
				journey.setDepartureTime(cells.get(1).text());
				journey.setArrivalTime(cells.get(2).text());
				journey.setDuration(cells.get(3).text());
				
				// the fee map for the particular journey
				Map<String, String> feeMap = new HashMap<String,String>();
				// get the fares
				Elements feeRows = cells.get(4).select("tbody tr");
				
				/* According to Renfe's website we select the following sublist */
				int fromIndex = 1;                    // skip the header row
				/* They present 2 set of fares (Internet and station) so we skip
				 * the header rows and divide by 2 to get the amount of fares to 
				 * parse */
				int toIndex = 1+(feeRows.size()-2)/2; 
				
				for(Element feeRow : feeRows.subList(fromIndex, toIndex)) {
					Elements feeCells = feeRow.getElementsByTag("td");
//					String feeName = feeCells.get(1).text().toLowerCase().replace(" ", "").replace(":", "").replace("ñ", "n");
					String feeName = feeCells.get(1).text().replace(":", "");
					String price = feeCells.get(2).text().replace(",", ".");
					// Set the fee
					feeMap.put(feeName, price);
				}
				
				// Set the fares
				journey.setFares(feeMap);
				retList.add(journey);
			}
		}

		return retList;
	}

	/**
	 * try it
	 * @param args
	 * @throws IOException
	 */
	public static void main(String [] args) throws IOException{
		RenfeScrapper rs = new RenfeScrapper();
		List<Perceptable> list = rs.getSchedule ("Madrid", "ciudad real", "16", "04", "2012");
		for(Perceptable journey : list){
			System.out.println(journey);
		}
	}
	
}
