/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.tajo.storage.jdbc;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tajo.catalog.*;
import org.apache.tajo.catalog.statistics.TableStats;
import org.apache.tajo.common.TajoDataTypes.Type;
import org.apache.tajo.exception.SQLExceptionUtil;
import org.apache.tajo.exception.TajoInternalError;
import org.apache.tajo.exception.UndefinedTablespaceException;
import org.apache.tajo.exception.UnsupportedDataTypeException;
import org.apache.tajo.util.KeyValueSet;
import org.apache.tajo.util.Pair;

import javax.annotation.Nullable;
import java.net.URI;
import java.sql.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import static org.apache.tajo.catalog.CatalogUtil.newSimpleDataType;

public abstract class JdbcMetadataProviderBase implements MetadataProvider {
  protected static final Log LOG = LogFactory.getLog(JdbcMetadataProviderBase.class);

  public static String [] GENERAL_TABLE_TYPES = new String [] {"TABLE"};

  protected final JdbcTablespace space;
  protected final String databaseName;

  protected final String jdbcUri;

  protected final Connection connection;

  public JdbcMetadataProviderBase(JdbcTablespace space, String dbName) {
    this.space = space;
    this.databaseName = dbName;

    ConnectionInfo connInfo = ConnectionInfo.fromURI(space.getUri());
    this.jdbcUri  = space.getUri().toASCIIString();

    try {
      Class.forName(getJdbcDriverName()).newInstance();
      LOG.info(getJdbcDriverName() + " is loaded...");
    } catch (Exception e) {
      throw new TajoInternalError(e);
    }

    try {
      connection = DriverManager.getConnection(jdbcUri, space.connProperties);
    } catch (SQLException e) {
      throw new TajoInternalError(e);
    }
  }

  @Override
  public String getTablespaceName() {
    return space.getName();
  }

  @Override
  public URI getTablespaceUri() {
    return space.getUri();
  }

  @Override
  public String getDatabaseName() {
    return databaseName;
  }

  @Override
  public Collection<String> getSchemas() {
    return Collections.EMPTY_SET;
  }

  @Override
  public Collection<String> getTables(@Nullable String schemaPattern, @Nullable String tablePattern) {
    ResultSet res = null;
    List<String> tableNames = Lists.newArrayList();
    try {
      res = connection.getMetaData().getTables(databaseName, schemaPattern, tablePattern, GENERAL_TABLE_TYPES);
      while(res.next()) {
        tableNames.add(res.getString("TABLE_NAME"));
      }
    } catch (SQLException e) {
      throw new TajoInternalError(e);
    } finally {
      try {
        if (res != null) {
          res.close();
        }
      } catch (SQLException e) {
        LOG.warn(e);
      }
    }

    return tableNames;
  }

  private TypeDesc convertDataType(ResultSet res) throws SQLException {
    final int typeId = res.getInt("DATA_TYPE");

    switch (typeId ) {
    case Types.BOOLEAN:
      return new TypeDesc(newSimpleDataType(Type.BOOLEAN));

    case Types.TINYINT:
    case Types.SMALLINT:
    case Types.INTEGER:
      return new TypeDesc(newSimpleDataType(Type.INT4));

    case Types.DISTINCT: // sequence for postgresql
    case Types.BIGINT:
      return new TypeDesc(newSimpleDataType(Type.INT8));

    case Types.FLOAT:
      return new TypeDesc(newSimpleDataType(Type.FLOAT4));

    case Types.NUMERIC:
    case Types.DECIMAL:
    case Types.DOUBLE:
      return new TypeDesc(newSimpleDataType(Type.FLOAT8));

    case Types.DATE:
      return new TypeDesc(newSimpleDataType(Type.DATE));

    case Types.TIME:
      return new TypeDesc(newSimpleDataType(Type.TIME));

    case Types.TIMESTAMP:
      return new TypeDesc(newSimpleDataType(Type.TIMESTAMP));

    case Types.CHAR:
    case Types.NCHAR:
    case Types.VARCHAR:
    case Types.NVARCHAR:
    case Types.CLOB:
    case Types.NCLOB:
    case Types.LONGVARCHAR:
    case Types.LONGNVARCHAR:
      return new TypeDesc(newSimpleDataType(Type.TEXT));

    case Types.BINARY:
    case Types.VARBINARY:
    case Types.BLOB:
      return new TypeDesc(newSimpleDataType(Type.BLOB));

    default:
      throw SQLExceptionUtil.toSQLException(new UnsupportedDataTypeException(typeId + ""));
    }
  }

  @Override
  public TableDesc getTableDesc(String schemaName, String tableName) throws UndefinedTablespaceException {
    ResultSet resultForTable = null;
    ResultSet resultForColumns = null;
    try {

      // get table name
      resultForTable = connection.getMetaData().getTables(databaseName, schemaName, tableName, null);

      if (!resultForTable.next()) {
        throw new UndefinedTablespaceException(tableName);
      }
      final String name = resultForTable.getString("TABLE_NAME");

      // get columns
      resultForColumns = connection.getMetaData().getColumns(databaseName, schemaName, tableName, null);

      final List<Pair<Integer, Column>> columns = Lists.newArrayList();

      while(resultForColumns.next()) {
        final int ordinalPos = resultForColumns.getInt("ORDINAL_POSITION");
        final String qualifier = resultForColumns.getString("TABLE_NAME");
        final String columnName = resultForColumns.getString("COLUMN_NAME");
        final TypeDesc type = convertDataType(resultForColumns);
        final Column c = new Column(CatalogUtil.buildFQName(databaseName, qualifier, columnName), type);

        columns.add(new Pair<>(ordinalPos, c));
      }

      // sort columns in an order of ordinal position
      Collections.sort(columns, new Comparator<Pair<Integer, Column>>() {
        @Override
        public int compare(Pair<Integer, Column> o1, Pair<Integer, Column> o2) {
          return o1.getFirst() - o2.getFirst();
        }
      });

      // transform the pair list into collection for columns
      final Schema schema = SchemaBuilder.builder().addAll(Collections2.transform(columns, new Function<Pair<Integer,Column>, Column>() {
        @Override
        public Column apply(@Nullable Pair<Integer, Column> columnPair) {
          return columnPair.getSecond();
        }
      })).build();


      // fill the table stats
      final TableStats stats = new TableStats();
      stats.setNumRows(-1); // unknown

      final TableDesc table = new TableDesc(
          CatalogUtil.buildFQName(databaseName, name),
          schema,
          new TableMeta("rowstore", new KeyValueSet()),
          space.getTableUri(databaseName, name)
      );
      table.setStats(stats);

      return table;

    } catch (SQLException e) {
      throw new TajoInternalError(e);
    } finally {
      try {
        if (resultForTable != null) {
          resultForTable.close();
        }

        if (resultForColumns != null) {
          resultForColumns.close();
        }

      } catch (SQLException e) {
        LOG.warn(e);
      }
    }
  }

  protected abstract String getJdbcDriverName();
}
