/**
 * 
 */
package eu.dnetlib.data.collective.transformation.engine.functions;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
//import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
//import java.util.Map;




import org.apache.oro.text.perl.Perl5Util;


/**
 * @author jochen
 *
 */
public class DateVocabulary extends Vocabulary{

	private static final String filterFuncMin = "min()";
	private String pattern_1 = "/^(\\d{4,4}-\\d{1,2}-\\d{1,2})/";
	private String pattern_2 = "/^(\\d{4,4}-\\d{1,2})$/";
	private String pattern_3 = "/^(\\d{4,4})$/";
	private String pattern_4 = "/^(\\d{1,2}.\\d{1,2}.\\d{4,4})$/";
	private SimpleDateFormat df;
	
	private transient Perl5Util perl5 = new Perl5Util();

	public String encoding(List<String> aKeys) throws ProcessingException{
		String tempKey_1 = null;
		String tempKey_2 = null;
		String tempKey_3 = null;
		String currentKey = null;
		String twoDigitFormat = String.format("%%0%dd", 2);

		try{
			for (String key: aKeys){
				key = key.trim();
				currentKey = key;
				if (perl5.match(pattern_1, key)){
					String[] dateSplitted = perl5.getMatch().toString().split("-");
					String dateNormalized = dateSplitted[0] + "-" + String.format(twoDigitFormat, Integer.parseInt(dateSplitted[1])) + "-" + String.format(twoDigitFormat, Integer.parseInt(dateSplitted[2]));
					return dateNormalized;
				}else if (perl5.match(pattern_2, key)){
					String[] dateSplitted = key.split("-");
					tempKey_1 = dateSplitted[0] + "-" + String.format(twoDigitFormat, Integer.parseInt(dateSplitted[1])) + "-01";
				}else if (perl5.match(pattern_3, key)){
					tempKey_2 = key + "-01-01";
				}else if (perl5.match(pattern_4, key)){
					String[] components = key.split("[\\-\\/\\.]");
					// ignore this key if it has less than 3 components
					if (components.length >= 3)
						tempKey_3 = components[2] + "-" + String.format(twoDigitFormat, Integer.parseInt(components[1])) + "-" + String.format(twoDigitFormat, Integer.parseInt(components[0]));					
				}
			}			
		}catch(Throwable e){
			throw new ProcessingException("Exception thrown in Datevocabulary (tried to match for value '" + currentKey + "'):", e);
		}
		if (tempKey_1 != null){
			return tempKey_1;
		}else if (tempKey_2 != null){
			return tempKey_2;
		}else if (tempKey_3 != null){
			return tempKey_3;
		}else{
			return "";			
		}
	}
	
	@Override
	public List<String> encoding(List<String> aKeys, String aDefaultPattern,
			String aFilterFunction) throws ProcessingException {
		List<String> evList = new LinkedList<String>();
		df = new SimpleDateFormat(aDefaultPattern);
		for (String v: aKeys){
			String ev = encoding(Arrays.asList(new String[]{v}));
			if (ev.length() > 0){
				try {
					if (aFilterFunction.trim().length() > 0 && !evList.isEmpty())
						evList.add( filter(df.parse(ev), df.parse(evList.remove(0)), aFilterFunction) );
					else
						evList.add(df.format(df.parse(ev)));
				} catch (ParseException e) {
					throw new ProcessingException("invalid date format: " + ev);
				}
			}
		}
		return evList;
	}
	
	private String filter(Date d1, Date d2, String filter) throws ProcessingException{
		if (filter.equals(filterFuncMin))
			if (d1.before(d2))
				return df.format(d1);
			else
				return df.format(d2);
		else
			throw new ProcessingException("unsupported filter function: " + filter);
	}
	
}
