package ff.sql.dialect.functions;

import org.apache.calcite.sql.SqlFunction;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlWindow;

import ff.sql.FunctionSupport;

/**
 *
 * @author fernandojerez
 */
public class SqliteDateFunctions extends DateFunctions {

	private void convertTo(final String part, final FunctionSupport support) {
		if ("Y".equals(part)) {
			support.append("/" + 60 * 60 * 24 * 365);
			return;
		}
		if ("M".equals(part)) {
			support.append("/" + 60 * 60 * 24 * 30);
			return;
		}
		if ("D".equals(part)) {
			support.append("/" + 60 * 60 * 24);
			return;
		}
		if ("H".equals(part)) {
			support.append("/" + 60 * 60);
			return;
		}
		if ("MI".equals(part)) {
			support.append("/" + 60);
			return;
		}
		if ("S".equals(part)) {
			return;
		}
		if ("MS".equals(part)) {
			support.append("* 1000");
			return;
		}
		throw new RuntimeException("Unsupported date part " + part);
	}

	private void convertUp(final String part, final FunctionSupport support) {
		if ("Y".equals(part)) {
			support.append("*" + 60 * 60 * 24 * 365);
			return;
		}
		if ("M".equals(part)) {
			support.append("*" + 60 * 60 * 24 * 30);
			return;
		}
		if ("D".equals(part)) {
			support.append("*" + 60 * 60 * 24);
			return;
		}
		if ("H".equals(part)) {
			support.append("*" + 60 * 60);
			return;
		}
		if ("MI".equals(part)) {
			support.append("*" + 60);
			return;
		}
		if ("S".equals(part)) {
			return;
		}
		if ("MS".equals(part)) {
			support.append("/ 1000");
			return;
		}
		throw new RuntimeException("Unsupported date part " + part);
	}

	@Override
	public String getDatePart(final String part) {
		if ("Y".equals(part)) {
			return "%Y";
		}
		if ("M".equals(part)) {
			return "%m";
		}
		if ("D".equals(part)) {
			return "%d";
		}
		if ("H".equals(part)) {
			return "%H";
		}
		if ("MI".equals(part)) {
			return "%M";
		}
		if ("S".equals(part)) {
			return "%S";
		}
		throw new RuntimeException("Unsupported date part " + part);
	}

	@Override
	protected void processDateAdd(final FunctionSupport support, final SqlFunction function, final SqlNode[] args,
			final SqlWindow window) {
		final String part = getDatePartFromNode(args[0]);
		support.append("datetime(strftime('%s',");
		support.processNode(args[2]);
		support.append(") + (");
		support.processNode(args[1]);
		convertUp(part, support);
		support.append(")");
		support.append(",'unixepoch')");
	}

	@Override
	protected void processDateDiff(final FunctionSupport support, final SqlFunction function, final SqlNode[] args,
			final SqlWindow window) {
		final String part = getDatePartFromNode(args[0]);
		support.append("(strftime('%s',");
		support.processNode(args[1]);
		support.append(") - strftime('%s',");
		support.processNode(args[2]);
		support.append("))");
		convertTo(part, support);
	}

	@Override
	protected void processDatePart(final FunctionSupport support, final SqlFunction function, final SqlNode[] args,
			final SqlWindow window) {
		support.append("strftime('");
		support.append(getDatePart(getDatePartFromNode(args[0])));
		support.append("',");
		support.processNode(args[1]);
		support.append(")");
	}

	@Override
	protected void processDateTrunc(final FunctionSupport support, final SqlFunction function, final SqlNode[] args,
			final SqlWindow window) {
		final String part = getDatePartFromNode(args[0]);
		support.append("datetime(strftime('%s',datetime('1000-01-01')) + ((strftime('%s',");
		support.processNode(args[1]);
		support.append(") - strftime('%s',datetime('1000-01-01')))");
		convertTo(part, support);
		convertUp(part, support);
		support.append("),'unixepoch')");
	}

	@Override
	protected void processToDate(final FunctionSupport support, final SqlFunction function, final SqlNode[] args,
			final SqlWindow window) {
		support.append("datetime(");
		support.processNode(args[0]);
		support.append(")");
	}

	@Override
	protected void processToTimestamp(final FunctionSupport support, final SqlFunction function, final SqlNode[] args,
			final SqlWindow window) {
		support.append("datetime(");
		support.processNode(args[0]);
		support.append(")");
	}

}
