/***************************************************************************
   Copyright 2012 Emily Estes

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
***************************************************************************/
package net.metanotion.sqlc;


import java.util.HashMap;

import net.metanotion.scripting.StructManager;
import net.metanotion.sqlc.setters.*;

import net.metanotion.util.types.Parser;

public final class SQLTypes {
	private static enum SET_TYPES {
		Array {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetArray(count, name, suffix);
			} },
		BigDecimal {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetBigDecimal(count, name, suffix);
			} },
		Boolean {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetBoolean(count, name, suffix);
			} },
		Date {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetDate(count, name, suffix);
			} },
		Double {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetDouble(count, name, suffix);
			} },
		Float {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetFloat(count, name, suffix);
			} },
		Integer {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetInteger(count, name, suffix);
			} },
		Instant {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetInstant(count, name, suffix);
			} },
		JsonObject {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetJsonObject(count, name, suffix);
			} },
		Long {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetLong(count, name, suffix);
			} },
		Object {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetObject(count, name, suffix);
			} },
		String {
			public SQLSetter get(final int count, final String name, final String suffix) {
				return new SetString(count, name, suffix);
			} };
		public abstract SQLSetter get(int count, String name, String suffix);
	}

	private static enum GET_TYPES {
		Array { public RSGetter get(final String name) { return new GetArray(name); } },
		BigDecimal { public RSGetter get(final String name) { return new GetBigDecimal(name); } },
		Boolean { public RSGetter get(final String name) { return new GetBoolean(name); } },
		Date { public RSGetter get(final String name) { return new GetDate(name); } },
		Double { public RSGetter get(final String name) { return new GetDouble(name); } },
		Float { public RSGetter get(final String name) { return new GetFloat(name); } },
		Integer { public RSGetter get(final String name) { return new GetInteger(name); } },
		Instant { public RSGetter get(final String name) { return new GetInstant(name); } },
		JsonObject { public RSGetter get(final String name) { return new GetJsonObject(name); } },
		Long { public RSGetter get(final String name) { return new GetLong(name); } },
		RowMap { public RSGetter get(final String name) { return new GetRowMap(name); } },
		Object { public RSGetter get(final String name) { return new GetObject(name); } },
		String { public RSGetter get(final String name) { return new GetString(name); } };
		public abstract RSGetter get(String name);
	}

	private static final HashMap<String,SET_TYPES> setterMap = new HashMap<String,SET_TYPES>();
	private static final HashMap<String,GET_TYPES> getterMap = new HashMap<String,GET_TYPES>();
	static {
		setterMap.put("Array", SET_TYPES.Array);
		setterMap.put("java.math.BigDecimal", SET_TYPES.BigDecimal);
		setterMap.put("Boolean", SET_TYPES.Boolean);
		setterMap.put("boolean", SET_TYPES.Boolean);
		setterMap.put("java.util.Date", SET_TYPES.Date);
		setterMap.put("Double", SET_TYPES.Double);
		setterMap.put("double", SET_TYPES.Double);
		setterMap.put("Float", SET_TYPES.Float);
		setterMap.put("float", SET_TYPES.Float);
		setterMap.put("Integer", SET_TYPES.Integer);
		setterMap.put("org.joda.time.ReadableInstant", SET_TYPES.Instant);
		setterMap.put("int", SET_TYPES.Integer);
		setterMap.put("net.metanotion.json.JsonObject", SET_TYPES.JsonObject);
		setterMap.put("Long", SET_TYPES.Long);
		setterMap.put("long", SET_TYPES.Long);
		setterMap.put("Object", SET_TYPES.Object);
		setterMap.put("String", SET_TYPES.String);
		setterMap.put("Text", SET_TYPES.String);
		setterMap.put("Varchar", SET_TYPES.String);

		getterMap.put("Array", GET_TYPES.Array);
		getterMap.put("java.math.BigDecimal", GET_TYPES.BigDecimal);
		getterMap.put("Boolean", GET_TYPES.Boolean);
		getterMap.put("boolean", GET_TYPES.Boolean);
		getterMap.put("java.util.Date", GET_TYPES.Date);
		getterMap.put("Double", GET_TYPES.Double);
		getterMap.put("double", GET_TYPES.Double);
		getterMap.put("Float", GET_TYPES.Float);
		getterMap.put("float", GET_TYPES.Float);
		getterMap.put("Integer", GET_TYPES.Integer);
		getterMap.put("org.joda.time.ReadableInstant", GET_TYPES.Instant);
		getterMap.put("int", GET_TYPES.Integer);
		getterMap.put("net.metanotion.json.JsonObject", GET_TYPES.JsonObject);
		getterMap.put("java.util.Map<String,Object>", GET_TYPES.RowMap);
		getterMap.put("Long", GET_TYPES.Long);
		getterMap.put("long", GET_TYPES.Long);
		getterMap.put("Object", GET_TYPES.Object);
		getterMap.put("String", GET_TYPES.String);
		getterMap.put("Text", GET_TYPES.String);
		getterMap.put("Varchar", GET_TYPES.String);
	}

	public SQLSetter getSetter(final int count, final String name, final String suffix, final String type) {
		final SET_TYPES s = setterMap.get(type);
		if(s == null) {
			return setterMap.get("Object").get(count, name, suffix);
		} else {
			return s.get(count, name, suffix);
		}
	}

	public boolean isPrimitive(final String type) {
		if("void".equals(type)) { return true; }
		return (getterMap.get(type) != null);
	}

	public RSGetter getGetter(final String name, final String type) {
		final GET_TYPES g = getterMap.get(type);
		if(g == null) {
			return getterMap.get("Object").get(name);
		} else {
			return g.get(name);
		}
	}

	public Parser getter(final String type, final StructManager sm, final RSGetter[] getters) {
		final GET_TYPES g = getterMap.get(type);
		if(g == null) {
			return new StructGetter(getters, sm, type);
		} else {
			return new ValueGetter(g.get(""));
		}
	}
}
