package com.infoteria.asteria.flowlibrary2.mapper.date;

import com.infoteria.asteria.flowengine2.execute.ExecuteContext;
import com.infoteria.asteria.flowlibrary2.mapper.MultiOutputFunction;
import com.infoteria.asteria.flowlibrary2.mapper.MapperException;
import com.infoteria.asteria.flowlibrary2.mapper.TimeZoneService;
import com.infoteria.asteria.value.Value;
import java.util.TimeZone;
import java.util.Calendar;
import java.util.Date;

public class DateSplit extends MultiOutputFunction {
	
	private static final String FUNCTION_NAME = "DateSplit";
	private static final String PROPERTY_TIMEZONE = "TimeZone";
	private static final String PROPERTY_MODE     = "Mode";
	private static final String PROPERTY_WEEKDAY  = "WeekDay";
	
	private static final String[] WEEKS_EN = {
		"Sun",
		"Mon",
		"Tue",
		"Wed",
		"Thu",
		"Fri",
		"Sat"
	};
	
	private static final String[] WEEKS_EN_FULL = {
		"Sunday",
		"Monday",
		"Tuesday",
		"Wednesday",
		"Thursday",
		"Friday",
		"Saturday"
	};
	
	private static final String[] WEEKS_JP = {
		"日",
		"月",
		"火",
		"水",
		"木",
		"金",
		"土"
	};
	
	public String getFunctionName() { return FUNCTION_NAME;}
	
	public DateSplit() {
		setSubValueCount(7);
	}
	
	protected void internalInit() {
		registProperty(PROPERTY_TIMEZONE, Value.TYPE_STRING, true);
		registProperty(PROPERTY_MODE, Value.TYPE_STRING, true);
		registProperty(PROPERTY_WEEKDAY, Value.TYPE_STRING, false);
	}
	
	public int getMinInputCount() { return 1;}
	public int getMaxInputCount() { return 1;}
	
	public void execute(ExecuteContext context, Value[] in, Value out) throws MapperException {
		Date v = in[0].dateValue();
		Calendar cal = getPropertyCalendar();
		cal.setTime(v);
		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day = cal.get(Calendar.DATE);
		int week = cal.get(Calendar.DAY_OF_WEEK);
		int hour = cal.get(Calendar.HOUR_OF_DAY);
		int min = cal.get(Calendar.MINUTE);
		int sec = cal.get(Calendar.SECOND);
		int ms = cal.get(Calendar.MILLISECOND);
		if ("Time".equals(getPropertyString(PROPERTY_MODE))) {
			out.setValue(hour);
			getSubValue(0).setValue(min);
			getSubValue(1).setValue(sec);
			getSubValue(2).setValue(ms);
		} else {
			out.setValue(year);
			getSubValue(0).setValue(month);
			getSubValue(1).setValue(day);
			getSubValue(2).setValue(getDayOfWeek(week));
			getSubValue(3).setValue(hour);
			getSubValue(4).setValue(min);
			getSubValue(5).setValue(sec);
			getSubValue(6).setValue(ms);
		}
	}
	
	private String getDayOfWeek(int w) {
		String s = getPropertyString(PROPERTY_WEEKDAY);
		if ("jp".equals(s))
			return WEEKS_JP[w-1];
		else if ("en".equals(s))
			return WEEKS_EN[w-1];
		else if ("EN".equals(s))
			return WEEKS_EN_FULL[w-1];
		else
			return Integer.toString(w);
	}
	
	////////////////////////////////////////
	// Copy from DateFunction
	////////////////////////////////////////
	private Calendar getPropertyCalendar()
	{
		return Calendar.getInstance(getPropertyTimeZone());
	}
	
	private TimeZone getPropertyTimeZone()
	{
		Value v = getProperty(PROPERTY_TIMEZONE);
		if (v == null)
			return TimeZoneService._utc_timezone;
		else
			return TimeZoneService.getTimeZone(v.strValue());
	}
}
