package com.wecise.odb.jdbc;

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

public class ODBResultSetMetaData implements ResultSetMetaData {

    /**
     * Names of columns
     */
    private String[] columnNames;
    private String[] columnLabels;
    private String[] columnTypes;
    private int[] columnDisplaySizes;
    /**
     * Name of table
     */
    private String tableName;

    ODBResultSetMetaData(String tableName, String[] columnNames, String[] columnLabels, String[] columnTypes, int[] columnDisplaySizes) {
        this.tableName = tableName;
        this.columnNames = columnNames;
        this.columnLabels = columnLabels;
        this.columnTypes = columnTypes;
        this.columnDisplaySizes = columnDisplaySizes;
    }

    @Override
    public int getColumnCount() throws SQLException {
        return this.columnTypes == null ? 0:this.columnTypes.length;
    }

    @Override
    public boolean isAutoIncrement(int i) throws SQLException {
        return false;
    }

    @Override
    public boolean isCaseSensitive(int i) throws SQLException {
        // all columns are lowercase
        return false;
    }

    @Override
    public boolean isSearchable(int i) throws SQLException {
        // the implementation doesn't support the where clause
        return false;
    }

    @Override
    public boolean isCurrency(int i) throws SQLException {
        return false;
    }

    @Override
    public int isNullable(int i) throws SQLException {
        return ResultSetMetaData.columnNullableUnknown;
    }

    @Override
    public boolean isSigned(int i) throws SQLException {
        return false;
    }

    @Override
    public int getColumnDisplaySize(int i) throws SQLException {
        return this.columnDisplaySizes[i - 1];
    }

    @Override
    public String getColumnLabel(int i) throws SQLException {
        // SQL column numbers start at 1
        return this.columnLabels[i - 1];
    }

    @Override
    public String getColumnName(int i) throws SQLException {
        // SQL column numbers start at 1
        return this.columnNames[i - 1];
    }

    @Override
    public String getSchemaName(int i) throws SQLException {
        return "";
    }

    @Override
    public int getPrecision(int i) throws SQLException {
        // What does it mean?
        return 0;
    }

    @Override
    public int getScale(int i) throws SQLException {
        // What does it mean?
        return 0;
    }

    @Override
    public String getTableName(int i) throws SQLException {
        return this.tableName;
    }

    @Override
    public String getCatalogName(int i) throws SQLException {
        return "";
    }

    private Map<String, Integer> typeNameToTypeCode = new HashMap<String, Integer>() {
        private static final long serialVersionUID = -8819579540085202365L;
        {
            put("varchar", Types.VARCHAR);
            put("text", Types.LONGVARCHAR);
            put("int", Types.INTEGER);
            put("smallint", Types.SMALLINT);
            put("bigint", Types.BIGINT);
            put("float", Types.FLOAT);
            put("double", Types.DOUBLE);
            put("date", Types.DATE);
            put("timestamp", Types.TIMESTAMP);
            put("blob", Types.BLOB);
            // collection
            put("map", Types.JAVA_OBJECT);
            put("list", Types.JAVA_OBJECT);
            put("set", Types.JAVA_OBJECT);
            put("bucket", Types.JAVA_OBJECT);
//            put("Boolean", Types.BOOLEAN);
//            put("Byte", Types.TINYINT);
//            put("Short", Types.SMALLINT);
//            put("Integer", Types.INTEGER);
//            put("BigDecimal", Types.DECIMAL);
//            put("Time", Types.TIME);
//            put("Clob", Types.CLOB);
//            put("expression", Types.BLOB);
        }
    };

    @Override
    public int getColumnType(int i) throws SQLException {
        String columnTypeName = getColumnTypeName(i);
        return typeNameToTypeCode.get(columnTypeName);
    }

    @Override
    public String getColumnTypeName(int i) throws SQLException {
        return this.columnTypes[i - 1];
    }

    @Override
    public boolean isReadOnly(int i) throws SQLException {
        return true;
    }

    @Override
    public boolean isWritable(int i) throws SQLException {
        return false;
    }

    @Override
    public boolean isDefinitelyWritable(int i) throws SQLException {
        return false;
    }

    @Override
    public String getColumnClassName(int i) throws SQLException {
        return this.columnTypes[i - 1];
    }

    @Override
    public <T> T unwrap(Class<T> aClass) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> aClass) throws SQLException {
        return false;
    }
}
