/*
 * 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.openjpa.jdbc.kernel;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.QualifiedDBIdentifier;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.schema.Schema;
import org.apache.openjpa.jdbc.schema.SchemaGroup;
import org.apache.openjpa.jdbc.schema.SchemaTool;
import org.apache.openjpa.jdbc.schema.Schemas;
import org.apache.openjpa.jdbc.schema.Sequence;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.lib.conf.Configurable;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.Options;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.UserException;

///////////////////////////////////////////////////////////
// NOTE: Do not change property names; see SequenceMetaData
// and SequenceMapping for standard property names.
////////////////////////////////////////////////////////////

/**
 * {@link JDBCSeq} implementation that uses a database sequence
 * to generate numbers.
 * Supports allocation (caching). In order for allocation to work properly, the database sequence must be defined
 * with INCREMENT BY value equal to allocate * increment.
 *
 * @see JDBCSeq
 * @see AbstractJDBCSeq
 */
public class NativeJDBCSeq
    extends AbstractJDBCSeq
    implements Configurable {

    public static final String ACTION_DROP = "drop";
    public static final String ACTION_ADD = "add";
    public static final String ACTION_GET = "get";

    private static Localizer _loc = Localizer.forPackage(NativeJDBCSeq.class);

    private JDBCConfiguration _conf = null;
    private DBIdentifier _seqName = DBIdentifier.newSequence("OPENJPA_SEQUENCE");
    private int _increment = 1;
    private int _initial = 1;
    private int _allocate = 50;
    private Sequence _seq = null;
    private String _select = null;
    private long _nextValue = 0;
    private long _maxValue = -1;

    private DBIdentifier _schema = DBIdentifier.NULL;

    private boolean alterIncrementBy = false;
    private boolean alreadyLoggedAlterSeqFailure = false;
    private boolean alreadyLoggedAlterSeqDisabled = false;

    /**
     * The sequence name. Defaults to <code>OPENJPA_SEQUENCE</code>.
     */
    // @GETTER
    public String getSequence() {
        return _seqName.getName();
    }

    /**
     * The sequence name. Defaults to <code>OPENJPA_SEQUENCE</code>.
     */
    public void setSequence(String seqName) {
        _seqName = DBIdentifier.newSequence(seqName);
    }

    /**
     * @see Sequence#getInitialValue
     */
    public int getInitialValue() {
        return _initial;
    }

    /**
     * @see Sequence#setInitialValue
     */
    public void setInitialValue(int initial) {
        _initial = initial;
    }

    /**
     * @see Sequence#getAllocate
     */
    public int getAllocate() {
        return _allocate;
    }

    /**
     * @see Sequence#setAllocate
     */
    public void setAllocate(int allocate) {
        _allocate = allocate;
    }

    /**
     * @see Sequence#getIncrement
     */
    public int getIncrement() {
        return _increment;
    }

    /**
     * @see Sequence#setIncrement
     */
    public void setIncrement(int increment) {
        _increment = increment;
    }

    @Override
    public void addSchema(ClassMapping mapping, SchemaGroup group) {
        // sequence already exists?
        QualifiedDBIdentifier path = QualifiedDBIdentifier.getPath(_seqName);
        if (group.isKnownSequence(path))
            return;

        DBIdentifier schemaName = getSchemaIdentifier();
        if (DBIdentifier.isEmpty(schemaName)) {
            schemaName = path.getSchemaName();
            if (DBIdentifier.isEmpty(schemaName))
                schemaName = Schemas.getNewTableSchemaIdentifier(_conf);
        }

        // create table in this group
        Schema schema = group.getSchema(schemaName);
        if (schema == null)
            schema = group.addSchema(schemaName);
        schema.importSequence(_seq);
    }

    @Override
    public JDBCConfiguration getConfiguration() {
        return _conf;
    }

    @Override
    public void setConfiguration(Configuration conf) {
        _conf = (JDBCConfiguration) conf;
    }

    @Override
    public void startConfiguration() {
    }

    @Override
    public void endConfiguration() {
        buildSequence();

        DBDictionary dict = _conf.getDBDictionaryInstance();
        String format = dict.nextSequenceQuery;
        if (format == null) {
            throw new MetaDataException(_loc.get("no-seq-sql", _seqName));
        }

        String name = dict.getFullName(_seq);
        // Increment step is needed for Firebird which uses non-standard sequence fetch syntax.
        // Use String.valueOf to get rid of possible locale-specific number formatting.
        _select = MessageFormat.format(format, new Object[]{name, String.valueOf(_allocate * _increment)});

        type = dict.nativeSequenceType;
    }

    @Override
    protected synchronized Object nextInternal(JDBCStore store, ClassMapping mapping)
        throws SQLException {
        if (!alterIncrementBy) {
            allocateInternal(0, store, mapping);
            alterIncrementBy = true;
        }
        if (_nextValue >= _maxValue) {
            allocateInternal(0, store, mapping);
        }
        long result = _nextValue;
        _nextValue += _increment;
        return result;
    }

    /**
     * Allocate additional sequence values.
     * @param additional ignored - the allocation size is fixed and determined by allocate and increment properties.
     * @param store used to obtain connection
     * @param mapping ignored
     */
    @Override
    protected synchronized void allocateInternal(int additional, JDBCStore store, ClassMapping mapping)
        throws SQLException {
        Connection conn = getConnection(store);
        try {
            if (!alterIncrementBy) {
                DBDictionary dict = _conf.getDBDictionaryInstance();
                if (!dict.disableAlterSeqenceIncrementBy) {
                    // If this fails, we will warn the user at most one time and set _allocated and _increment to 1 so
                    // as to not potentially insert records ahead of what the database thinks is the next sequence
                    // value.

                    // first we have to allocate a new connection as some databases do an implicit commit
                    // if a DDL gets changed. Others do blow up on a DDL change
                    try (Connection newConn = getConnection(store, true)) {
                        if (updateSql(newConn, dict.getAlterSequenceSQL(_seq)) == -1) {
                            newConn.commit(); // new connection has autoCommit=false
                            if (!alreadyLoggedAlterSeqFailure) {
                                Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
                                if (log.isWarnEnabled()) {
                                    log.warn(_loc.get("fallback-no-seq-cache", _seqName));
                                }
                            }
                            alreadyLoggedAlterSeqFailure = true;
                            _allocate = 1;
                        }
                    }
                } else {
                    if (!alreadyLoggedAlterSeqDisabled) {
                        Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
                        if (log.isWarnEnabled()) {
                            log.warn(_loc.get("alter-seq-disabled", _seqName));
                        }
                    }

                    alreadyLoggedAlterSeqDisabled = true;
                }
            }
            _nextValue = getSequence(conn);
            _maxValue = _nextValue + _allocate * _increment;
        } finally {
            closeConnection(conn);
        }
    }

    /**
     * Creates the sequence object.
     */
    private void buildSequence() {
        QualifiedDBIdentifier path = QualifiedDBIdentifier.getPath(_seqName);
        DBIdentifier seqName = path.getIdentifier();
        // JPA 2 added schema as a configurable attribute on
        // sequence generator.  OpenJPA <= 1.x allowed this via
        // schema.sequence on the sequence name.  Specifying a schema
        // name on the annotation or in the orm will override the old
        // behavior.
        DBIdentifier schemaName = _schema;
        if (DBIdentifier.isEmpty(schemaName)) {
            schemaName = path.getSchemaName();
            if (DBIdentifier.isEmpty(schemaName))
                schemaName = Schemas.getNewTableSchemaIdentifier(_conf);
        }

        // build the sequence in one of the designated schemas
        SchemaGroup group = new SchemaGroup();
        Schema schema = group.addSchema(schemaName);

        _seq = schema.addSequence(seqName);
        _seq.setInitialValue(_initial);
        _seq.setIncrement(_increment);
        _seq.setAllocate(_allocate);
    }

    /**
     * Creates the sequence in the DB.
     */
    public void refreshSequence()
        throws SQLException {
        Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
        if (log.isInfoEnabled())
            log.info(_loc.get("make-native-seq"));

        // create the sequence
        SchemaTool tool = new SchemaTool(_conf);
        tool.setIgnoreErrors(true);
        tool.createSequence(_seq);
    }

    /**
     * Drops the sequence in the DB.
     */
    public void dropSequence()
        throws SQLException {
        Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
        if (log.isInfoEnabled())
            log.info(_loc.get("drop-native-seq"));

        // drop the table
        SchemaTool tool = new SchemaTool(_conf);
        tool.setIgnoreErrors(true);
        tool.dropSequence(_seq);
    }

    /**
     * Return the next sequence value.
     */
    private long getSequence(Connection conn)
        throws SQLException {
        DBDictionary dict = _conf.getDBDictionaryInstance();
        PreparedStatement stmnt = null;
        ResultSet rs = null;
        try {
            stmnt = conn.prepareStatement(_select);
            dict.setTimeouts(stmnt, _conf, false);
            rs = stmnt.executeQuery();
            if (rs.next())
                return rs.getLong(1);

            // no row !?
            throw new UserException(_loc.get("invalid-seq-sql", _select));
        } finally {
            // clean up our resources
            if (rs != null)
                try { rs.close(); } catch (SQLException se) {}
            if (stmnt != null)
                try { stmnt.close(); } catch (SQLException se) {}
        }
    }

    private int updateSql(Connection conn, String sql) throws SQLException {
        DBDictionary dict = _conf.getDBDictionaryInstance();
        PreparedStatement stmnt = null;
        int rc = -1;
        try {
            stmnt = conn.prepareStatement(sql);
            dict.setTimeouts(stmnt, _conf, false);
            rc = stmnt.executeUpdate();
        } catch (Exception e) {
            // tolerate exception when attempting to alter increment,
            // however, caller should check rc and not cache sequence values if rc != -1.
        } finally {
            // clean up our resources
            if (stmnt != null) {
                try {
                    stmnt.close();
                } catch (SQLException se) {
                }
            }
        }
        return rc;
    }

    /////////
    // Main
    /////////

    /**
     * Usage: java org.apache.openjpa.jdbc.schema.NativeJDBCSequence [option]*
     * -action/-a &lt;add | drop | get&gt;
     *  Where the following options are recognized.
     * <ul>
     * <li><i>-properties/-p &lt;properties file or resource&gt;</i>: The
     * path or resource name of an OpenJPA properties file containing
     * information such as connection data as
     * outlined in {@link JDBCConfiguration}. Optional.</li>
     * <li><i>-&lt;property name&gt; &lt;property value&gt;</i>: All bean
     * properties of the OpenJPA {@link JDBCConfiguration} can be set by
     * using their names and supplying a value.</li>
     * </ul>
     *  The various actions are as follows.
     * <ul>
     * <li><i>add</i>: Create the sequence.</li>
     * <li><i>drop</i>: Drop the sequence.</li>
     * <li><i>get</i>: Print the next sequence value.</li>
     * </ul>
     */
    public static void main(String[] args)
        throws Exception {
        Options opts = new Options();
        final String[] arguments = opts.setFromCmdLine(args);
        boolean ret = Configurations.runAgainstAllAnchors(opts,
            new Configurations.Runnable() {
            @Override
            public boolean run(Options opts) throws Exception {
                JDBCConfiguration conf = new JDBCConfigurationImpl();
                try {
                    return NativeJDBCSeq.run(conf, arguments, opts);
                } finally {
                    conf.close();
                }
            }
        });
        if (!ret) {
            // START - ALLOW PRINT STATEMENTS
            System.out.println(_loc.get("native-seq-usage"));
            // STOP - ALLOW PRINT STATEMENTS
        }
    }

    /**
     * Run the tool. Returns false if invalid options were given.
     */
    public static boolean run(JDBCConfiguration conf, String[] args,
        Options opts)
        throws Exception {
        String action = opts.removeProperty("action", "a", null);
        Configurations.populateConfiguration(conf, opts);
        return run(conf, args, action);
    }

    /**
     * Run the tool. Returns false if an invalid option was given.
     */
    public static boolean run(JDBCConfiguration conf, String[] args,
        String action)
        throws Exception {
        if (args.length != 0)
            return false;

        NativeJDBCSeq seq = new NativeJDBCSeq();
        String props = Configurations.getProperties(conf.getSequence());
        Configurations.configureInstance(seq, conf, props);

        if (ACTION_DROP.equals(action))
            seq.dropSequence();
        else if (ACTION_ADD.equals(action))
            seq.refreshSequence();
        else if (ACTION_GET.equals(action)) {
            Connection conn = conf.getDataSource2(null).getConnection();
            try {
                long cur = seq.getSequence(conn);
                // START - ALLOW PRINT STATEMENTS
                System.out.println(cur);
                // STOP - ALLOW PRINT STATEMENTS
            } finally {
                try { conn.close(); } catch (SQLException se) {}
            }
        } else
            return false;
        return true;
    }

    /**
     * @deprecated
     */
    @Deprecated
    public void setSchema(String schema) {
        _schema = DBIdentifier.newSchema(schema);
    }

    /**
     * @deprecated
     */
    @Deprecated
    public String getSchema() {
        return _schema.getName();
    }

    public DBIdentifier getSchemaIdentifier() {
        return _schema;
    }

}
