/*
 * JBoss, Home of Professional Open Source.
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 * Modified by
 * @author  Data Virtuality GmbH
 * @date    $Date$
 *  
 */

/*
 */
package org.teiid.translator.jdbc.informix;

import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.ClobImpl;
import org.teiid.core.types.ClobType;
import org.teiid.core.types.DataTypeManager;
import org.teiid.translator.SourceSystemFunctions;
import org.teiid.translator.Translator;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.jdbc.ConvertModifier;
import org.teiid.translator.jdbc.JDBCExecutionFactory;
import org.teiid.translator.jdbc.JDBCMetadataProcessor;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Translator(name="informix", description="A translator for Informix Database")
public class InformixExecutionFactory extends JDBCExecutionFactory {
	private static Map<String, Class<?>> typeMap = new HashMap<String, Class<?>>() {
		private static final long serialVersionUID = -145921355529005016L;

		@Override
		public Class<?> get(Object key) {
			return FakeSQLData.class;
		}
	};
//	static {
//		typeMap = new HashMap<>();
//		typeMap.put("sysbldsqltext", FakeSQLData.class);
//		typeMap.put("calendar", FakeSQLData.class);
//	}

	@Override
	public void obtainedConnection(Connection connection) {
		super.obtainedConnection(connection);
		try {
			connection.setTypeMap(typeMap);
		} catch (SQLException e) {
			throw new TeiidRuntimeException(e);
		}
	}

	@Override
	public void start() throws TranslatorException {
		super.start();
		setForceQuotedIdentifiers(false);
    	registerFunctionModifier(SourceSystemFunctions.CONVERT, new ConvertModifier());
    }

	@Override
    public List getSupportedFunctions() {
        List supportedFunctons = new ArrayList();
        supportedFunctons.addAll(super.getSupportedFunctions());
        supportedFunctons.add("CAST"); //$NON-NLS-1$
        supportedFunctons.add("CONVERT"); //$NON-NLS-1$
        return supportedFunctons;
    }
	
	protected JDBCMetadataProcessor createMetadataProcessor() {
		JDBCMetadataProcessor metadataProcessor = new InformixMetadataProcessor();
		return metadataProcessor;
	}

	@Override
	public JDBCMetadataProcessor.ITypeConverter getTypeConverter() {
		return new JDBCMetadataProcessor.ITypeConverter() {
			@Override
			public String getRuntimeType(int type, String typeName, int precision, int scale) {
				if ("VARIABLE UDT".equals(typeName))
					return DataTypeManager.DefaultDataTypes.OBJECT;
				if ("SENDRECEIVE".equals(typeName))
					return DataTypeManager.DefaultDataTypes.OBJECT;
				return null;
			}
		};
	}

	@Override
	public Object retrieveValue(ResultSet results, int columnIndex, Class<?> expectedType) throws SQLException {
		if (Object.class.equals(expectedType))
			return results.getObject(columnIndex).toString();
		Object value = super.retrieveValue(results, columnIndex, expectedType);
		if (ClobType.class.equals(expectedType) && value instanceof Struct)
			value = ClobImpl.createClob(("[" + value.toString() + "]").toCharArray());
		if (ClobType.class.equals(expectedType) && value instanceof SQLData)
			value = ClobImpl.createClob(value.toString().toCharArray());
		return value;
	}

	@Override
    public boolean supportsRowLimit() {
    	return true;
    }
}
