/**
 * 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.netbeans.modules.db.metadata.model.jdbc;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.db.metadata.model.MetadataUtilities;
import org.netbeans.modules.db.metadata.model.api.Index.IndexType;
import org.netbeans.modules.db.metadata.model.api.*;
import org.netbeans.modules.db.metadata.model.spi.TableImplementation;
import org.openide.util.NbBundle;

/**
 *
 * @author Andrei Badea
 */
public class JDBCTable extends TableImplementation {

    private static final Logger LOGGER = Logger.getLogger(JDBCTable.class.getName());

    private final JDBCSchema jdbcSchema;
    private final String name;
    private final boolean system;

    private Map<String, Column> columns;
    private Map<String, Index> indexes;
    private Map<String, ForeignKey> foreignKeys;
    
    private PrimaryKey primaryKey;

    // Need a marker because there may be *no* primary key, and we don't want
    // to hit the database over and over again when there is no primary key
    private boolean primaryKeyInitialized = false;
    private static final String SQL_EXCEPTION_NOT_YET_IMPLEMENTED = "not yet implemented";

    public JDBCTable(JDBCSchema jdbcSchema, String name, boolean system) {
        this.jdbcSchema = jdbcSchema;
        this.name = name;
        this.system = system;
    }

    @Override
    public final Schema getParent() {
        return jdbcSchema.getSchema();
    }

    @Override
    public final String getName() {
        return name;
    }

    @Override
    public final Collection<Column> getColumns() {
        return initColumns().values();
    }

    @Override
    public final Column getColumn(String name) {
        return MetadataUtilities.find(name, initColumns());
    }

    @Override
    public PrimaryKey getPrimaryKey() {
        return initPrimaryKey();
    }

    @Override
    public Index getIndex(String indexName) {
        return MetadataUtilities.find(indexName, initIndexes());
    }

    @Override
    public Collection<Index> getIndexes() {
        return initIndexes().values();
    }

    @Override
    public Collection<ForeignKey> getForeignKeys() {
        return initForeignKeys().values();
    }

    @Override
    public ForeignKey getForeignKeyByInternalName(String name) {
         return MetadataUtilities.find(name, initForeignKeys());
    }

    @Override
    public final void refresh() {
        columns = null;
        primaryKey = null;
        primaryKeyInitialized = false;
    }

    @Override
    public boolean isSystem() {
        return system;
    }

    @Override
    public String toString() {
        return "JDBCTable[name='" + name + "']"; // NOI18N
    }

    protected JDBCColumn createJDBCColumn(ResultSet rs) throws SQLException {
        int position = 0;
        JDBCValue jdbcValue;
        if (isOdbc(rs)) {
            jdbcValue = JDBCValue.createTableColumnValueODBC(rs, this.getTable());
        } else {
            position = rs.getInt("ORDINAL_POSITION");
            jdbcValue = JDBCValue.createTableColumnValue(rs, this.getTable());
        }
        return new JDBCColumn(this.getTable(), position, jdbcValue);
    }

    /** Returns true if this table is under ODBC connection. In such a case
     * some meta data like ORDINAL_POSITION or ASC_OR_DESC are not supported. */
    private boolean isOdbc(ResultSet rs) throws SQLException {
        boolean odbc = jdbcSchema.getJDBCCatalog().getJDBCMetadata().getDmd().getURL().startsWith("jdbc:odbc");  //NOI18N
        if (odbc) {
            try {
                rs.getInt("PRECISION");
                return true;
            } catch (SQLException e) {
                // ignore and return false at the end; Probably MS Access driver which supports standards
            }
        }
        return false;
    }

    protected JDBCPrimaryKey createJDBCPrimaryKey(String pkName, Collection<Column> pkcols) {
        return new JDBCPrimaryKey(this.getTable(), pkName, pkcols);
    }

    protected void createColumns() {
        Map<String, Column> newColumns = new LinkedHashMap<String, Column>();
        try {
            ResultSet rs = MetadataUtilities.getColumns(
                    jdbcSchema.getJDBCCatalog().getJDBCMetadata().getDmd(),
                    jdbcSchema.getJDBCCatalog().getName(), jdbcSchema.getName(),
                    name, "%"); // NOI18N
            if (rs != null) {
                try {
                    while (rs.next()) {
                        Column column = createJDBCColumn(rs).getColumn();
                        newColumns.put(column.getName(), column);
                        LOGGER.log(Level.FINE, "Created column {0}", column); //NOI18N
                    }
                } finally {
                    rs.close();
                }
            }
        } catch (SQLException e) {
            filterSQLException(e);
        }
        columns = Collections.unmodifiableMap(newColumns);
    }

    protected void createIndexes() {
        Map<String, Index> newIndexes = new LinkedHashMap<String, Index>();
        try {
            ResultSet rs = MetadataUtilities.getIndexInfo(
                    jdbcSchema.getJDBCCatalog().getJDBCMetadata().getDmd(),
                    jdbcSchema.getJDBCCatalog().getName(), jdbcSchema.getName(),
                    name, false, true);
            if (rs != null) {
                try {
                    JDBCIndex index = null;
                    String currentIndexName = null;
                    while (rs.next()) {
                        // Ignore Indices marked statistic
                        // explicit: TYPE == DatabaseMetaData or
                        // implicit: ORDINAL_POSITION == 0
                        // @see java.sql.DatabaseMetaData#getIndexInfo
                        if (rs.getShort("TYPE") //NOI18N
                                == DatabaseMetaData.tableIndexStatistic
                                || rs.getInt("ORDINAL_POSITION") == 0) { //NOI18N
                            continue;
                        }

                        String indexName = MetadataUtilities.trimmed(rs.getString("INDEX_NAME")); //NOI18N
                        if (index == null || !(currentIndexName.equals(indexName))) {
                            index = createJDBCIndex(indexName, rs);
                            LOGGER.log(Level.FINE, "Created index {0}", index); //NOI18N

                            newIndexes.put(index.getName(), index.getIndex());
                            currentIndexName = indexName;
                        }

                        JDBCIndexColumn idx = createJDBCIndexColumn(index, rs);
                        if (idx == null) {
                            LOGGER.log(Level.INFO, "Cannot create index column for {0} from {1}",  //NOI18N
                                    new Object[]{indexName, rs});
                        } else {
                            IndexColumn col = idx.getIndexColumn();
                            index.addColumn(col);
                            LOGGER.log(Level.FINE, "Added column {0} to index {1}",   //NOI18N
                                    new Object[]{col.getName(), indexName});
                        }
                    }
                } finally {
                    rs.close();
                }
            }
        } catch (SQLException e) {
            filterSQLException(e);
        }

        indexes = Collections.unmodifiableMap(newIndexes);
    }

    protected JDBCIndex createJDBCIndex(String name, ResultSet rs) {
        IndexType type = IndexType.OTHER;
        boolean isUnique = false;
        try {
            type = JDBCUtils.getIndexType(rs.getShort("TYPE"));
            isUnique = !rs.getBoolean("NON_UNIQUE");
        } catch (SQLException e) {
            filterSQLException(e);
        }
        return new JDBCIndex(this.getTable(), name, type, isUnique);
    }

    protected JDBCIndexColumn createJDBCIndexColumn(JDBCIndex parent, ResultSet rs) {
        Column column = null;
        int position = 0;
        Ordering ordering = Ordering.NOT_SUPPORTED;
        try {
            column = getColumn(rs.getString("COLUMN_NAME"));
            if (!isOdbc(rs)) {
                position = rs.getInt("ORDINAL_POSITION");
                ordering = JDBCUtils.getOrdering(MetadataUtilities.trimmed(rs.getString("ASC_OR_DESC")));
            }
        } catch (SQLException e) {
            filterSQLException(e);
        }
        if (column == null) {
            LOGGER.log(Level.INFO, "Cannot get column for index {0} from {1}",  //NOI18N
                    new Object[] {parent, rs});
            return null;
        }
        return new JDBCIndexColumn(parent.getIndex(), column.getName(), column, position, ordering);
    }

        protected void createForeignKeys() {
        Map<String,ForeignKey> newKeys = new LinkedHashMap<String,ForeignKey>();
        try {
            ResultSet rs = MetadataUtilities.getImportedKeys(
                    jdbcSchema.getJDBCCatalog().getJDBCMetadata().getDmd(),
                    jdbcSchema.getJDBCCatalog().getName(), jdbcSchema.getName(),
                    name);
            if (rs != null) {
                try {
                    JDBCForeignKey fkey = null;
                    String currentKeyName = null;
                    while (rs.next()) {
                        String keyName = MetadataUtilities.trimmed(rs.getString("FK_NAME"));
                        // We have to assume that if the foreign key name is null, then this is a *new*
                        // foreign key, even if the last foreign key name was also null.
                    if (fkey == null || keyName == null || !(currentKeyName.equals(keyName))) {
                            fkey = createJDBCForeignKey(keyName, rs);
                            LOGGER.log(Level.FINE, "Created foreign key {0}", keyName);  //NOI18N

                            newKeys.put(fkey.getInternalName(), fkey.getForeignKey());
                            currentKeyName = keyName;
                        }

                        ForeignKeyColumn col = createJDBCForeignKeyColumn(fkey, rs).getForeignKeyColumn();
                        fkey.addColumn(col);
                        LOGGER.log(Level.FINE, "Added foreign key column {0} to foreign key {1}",  //NOI18N
                                new Object[]{col.getName(), keyName});
                    }
                } finally {
                    rs.close();
                }
            }
        } catch (SQLException e) {
            filterSQLException(e);
        }

        foreignKeys = Collections.unmodifiableMap(newKeys);
    }

    protected JDBCForeignKey createJDBCForeignKey(String name, ResultSet rs) {
        return new JDBCForeignKey(this.getTable(), name);
    }

    protected JDBCForeignKeyColumn createJDBCForeignKeyColumn(JDBCForeignKey parent, ResultSet rs) {
        Table table;
        String colname;
        Column referredColumn = null;
        Column referringColumn = null;
        int position = 0;

        try {
            table = findReferredTable(rs);
            colname = MetadataUtilities.trimmed(rs.getString("PKCOLUMN_NAME")); // NOI18N
            referredColumn = table.getColumn(colname);
            if (referredColumn == null) {
                throwColumnNotFoundException(table, colname);
            }

            colname = MetadataUtilities.trimmed(rs.getString("FKCOLUMN_NAME"));
            referringColumn = getColumn(colname);

            if (referringColumn == null) {
                throwColumnNotFoundException(this.getTable(), colname);
            }
            position = rs.getInt("KEY_SEQ");
        } catch (SQLException e) {
            filterSQLException(e);
        }
        return new JDBCForeignKeyColumn(parent.getForeignKey(), referringColumn.getName(), referringColumn, referredColumn, position);
    }
    
    private void throwColumnNotFoundException(Table table, String colname)
            throws MetadataException {
        String message = getMessage("ERR_COL_NOT_FOUND", //NOI18N
                table.getParent().getParent().getName(),
                table.getParent().getName(), table.getName(), colname);
        MetadataException e = new MetadataException(message);
        LOGGER.log(Level.INFO, message, e);
        throw e;
    }

    private String getMessage(String key, String ... args) {
        return NbBundle.getMessage(JDBCTable.class, key, args);
    }

    private Table findReferredTable(ResultSet rs) {
        JDBCMetadata metadata = jdbcSchema.getJDBCCatalog().getJDBCMetadata();
        Catalog catalog;
        Schema schema;
        Table table = null;

        try {
            String catalogName = MetadataUtilities.trimmed(rs.getString("PKTABLE_CAT")); // NOI18N
            if (catalogName == null || catalogName.length() == 0) {
                catalog = jdbcSchema.getParent();
            } else {
                catalog = metadata.getCatalog(catalogName);
                if (catalog == null) {
                    throw new MetadataException(getMessage("ERR_CATALOG_NOT_FOUND", catalogName)); // NOI18N
                }
            }

            String schemaName = MetadataUtilities.trimmed(rs.getString("PKTABLE_SCHEM")); // NOI18N

            if (schemaName == null || schemaName.length() == 0) {
                schema = catalog.getSyntheticSchema();
            } else {
                schema = catalog.getSchema(schemaName);
                if (schema == null) {
                    throw new MetadataException(getMessage("ERR_SCHEMA_NOT_FOUND", schemaName, catalog.getName()));
                }
            }

            String tableName = MetadataUtilities.trimmed(rs.getString("PKTABLE_NAME"));
            table = schema.getTable(tableName);

            if (table == null) {
                throw new MetadataException(getMessage("ERR_TABLE_NOT_FOUND", catalogName, schemaName, tableName));
            }

        } catch (SQLException e) {
            filterSQLException(e);
        }

        return table;
    }

    protected void createPrimaryKey() {
        String pkname = null;
        Collection<Column> pkcols = new ArrayList<Column>();
        try {
            ResultSet rs = MetadataUtilities.getPrimaryKeys(
                    jdbcSchema.getJDBCCatalog().getJDBCMetadata().getDmd(),
                    jdbcSchema.getJDBCCatalog().getName(), jdbcSchema.getName(),
                    name);
            if (rs != null) {
                try {
                    while (rs.next()) {
                        if (pkname == null) {
                            pkname = MetadataUtilities.trimmed(rs.getString("PK_NAME"));
                        }
                        String colName = MetadataUtilities.trimmed(rs.getString("COLUMN_NAME"));
                        pkcols.add(getColumn(colName));
                    }
                } finally {
                    rs.close();
                }
            }
        } catch (SQLException e) {
            filterSQLException(e);
        }

        primaryKey = createJDBCPrimaryKey(pkname, Collections.unmodifiableCollection(pkcols)).getPrimaryKey();
    }

    private Map<String, Column> initColumns() {
        if (columns != null) {
            return columns;
        }
        LOGGER.log(Level.FINE, "Initializing columns in {0}", this);
        createColumns();
        return columns;
    }

    private Map<String, Index> initIndexes() {
        if (indexes != null) {
            return indexes;
        }
        LOGGER.log(Level.FINE, "Initializing indexes in {0}", this);

        createIndexes();
        return indexes;
    }

    private Map<String,ForeignKey> initForeignKeys() {
        if (foreignKeys != null) {
            return foreignKeys;
        }
        LOGGER.log(Level.FINE, "Initializing foreign keys in {0}", this);

        createForeignKeys();
        return foreignKeys;
    }

    private PrimaryKey initPrimaryKey() {
        if (primaryKeyInitialized) {
            return primaryKey;
        }
        LOGGER.log(Level.FINE, "Initializing columns in {0}", this);
        // These need to be initialized first.
        getColumns();
        createPrimaryKey();
        primaryKeyInitialized = true;
        return primaryKey;
    }

    private void filterSQLException(SQLException x) throws MetadataException {
        if (SQL_EXCEPTION_NOT_YET_IMPLEMENTED.equalsIgnoreCase(x.getMessage())) {
            Logger.getLogger(JDBCTable.class.getName()).log(Level.FINE, x.getLocalizedMessage(), x);
        } else {
            throw new MetadataException(x);
        }
    }
}
