/*
 * 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.empire.dbms.oracle;

import java.util.ArrayList;
import java.util.List;

import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.DataType;
import org.apache.empire.db.DBColumn;
import org.apache.empire.db.DBColumnExpr;
import org.apache.empire.db.DBCommand;
import org.apache.empire.db.DBIndex;
import org.apache.empire.db.DBRowSet;
import org.apache.empire.db.exceptions.NoPrimaryKeyException;
import org.apache.empire.db.expr.column.DBAliasExpr;
import org.apache.empire.db.expr.column.DBValueExpr;
import org.apache.empire.db.expr.compare.DBCompareExpr;
import org.apache.empire.db.expr.set.DBSetExpr;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ObjectNotValidException;

/**
 * This class handles the special features of an oracle database.
 * 
 *
 */
public class DBCommandOracle extends DBCommand
{
    // *Deprecated* private static final long serialVersionUID = 1L;
  
    // Oracle Connect By / Start With
    protected DBCompareExpr connectBy  = null;
    protected DBCompareExpr startWith  = null;
    // optimizerHint
    protected String        optimizerHint  = null;
    // protected OracleRowNumExpr	rowNumExpr = null;
    protected int limitRows = -1;
    protected int skipRows  =  0;

    /**
     * Constructs an oracle command object.
     * 
     * @see org.apache.empire.db.DBCommand
     * 
     * @param db the oracle database object this command belongs to
     */
    public DBCommandOracle(boolean autoPrepareStmt)
    {
        super(autoPrepareStmt);
    }

    public String getOptimizerHint()
    {
        return optimizerHint;
    }

    public void setOptimizerHint(String optimizerHint)
    {
        this.optimizerHint = optimizerHint;
    }

    public void setOptimizerIndexHint(DBIndex index)
    {
        if (index==null || index.getTable()==null)
            throw new InvalidArgumentException("index", index);
        // Set Index Hint
        String tableAlias = index.getTable().getAlias();
        String indexName  = index.getName();
        String indexHint  = "INDEX ("+tableAlias+" "+indexName+")";
        if (StringUtils.isNotEmpty(this.optimizerHint) && this.optimizerHint.indexOf(indexHint)<0)
            this.optimizerHint = this.optimizerHint + " " + indexHint;
        else
            this.optimizerHint = indexHint;
    }

    /**
     * @see DBCommand#clear()
     */
    @Override
    public void clear()
    {
        super.clear();
        // Clear oracle specific properties
        clearConnectBy();
        optimizerHint = null;
    }

    /**
     * Clears the connectBy Expression.
     */
    public void clearConnectBy()
    {
        connectBy = startWith = null;
    }

    public void connectByPrior(DBCompareExpr expr)
    {
        this.connectBy = expr;
    }

    public void startWith(DBCompareExpr expr)
    {
        this.startWith = expr;
    }
    
    @Override
    public DBCommandOracle limitRows(int limitRows)
    {
        // set limit
        this.limitRows = limitRows;
        return this;
    }

    @Override
    public DBCommandOracle skipRows(int skipRows)
    {
        if (skipRows<0)
            throw new InvalidArgumentException("skipRows", skipRows);
        // set skip
        this.skipRows = skipRows;
        return this;
    }
     
    @Override
    public void clearLimit()
    {
    	// remove skip and limit
        this.limitRows = -1;
        this.skipRows  =  0;
    }

    /**
     * Creates an Oracle specific select statement
     * that supports special features of the Oracle DBMS
     * like e.g. CONNECT BY PRIOR
     * @param buf the SQL statement
     */
    @Override
    public synchronized void getSelect(StringBuilder buf)
    {        
        resetParamUsage();
        if (select == null)
            throw new ObjectNotValidException(this);
        // limit rows
        boolean usePreparedStatements = isPreparedStatementsEnabled();
        if (limitRows>=0)
        {   // add limitRows and skipRows wrapper
            buf.append("SELECT * FROM (");
            if (skipRows>0)
                buf.append("SELECT row_.*, rownum rownum_ FROM (");
        }
        // Prepares statement
        buf.append("SELECT ");
        if (StringUtils.isNotEmpty(optimizerHint))
        {   // Append an optimizer hint to the select statement e.g. SELECT /*+ RULE */
            buf.append("/*+ ").append(optimizerHint).append(" */ ");
        }
        if (selectDistinct)
            buf.append("DISTINCT ");
        // Add Select Expressions
        addListExpr(buf, select, CTX_ALL, ", ");
        // Join
        addFrom(buf);
        // Where
        addWhere(buf);
        // Connect By
        if (connectBy != null)
        {   // Add 'Connect By Prior' Expression
        	buf.append("\r\nCONNECT BY PRIOR ");
            connectBy.addSQL(buf, CTX_DEFAULT | CTX_NOPARENTHESES);
            // Start With
            if (startWith != null)
            {	// Add 'Start With' Expression
            	buf.append("\r\nSTART WITH ");
                startWith.addSQL(buf, CTX_DEFAULT);
            }
        }
        // Grouping
        addGrouping(buf);
        // Order
        if (orderBy != null)
        { // Having
            if (connectBy != null)
                buf.append("\r\nORDER SIBLINGS BY ");
            else
                buf.append("\r\nORDER BY ");
            // Add List of Order By Expressions
            addListExpr(buf, orderBy, CTX_DEFAULT, ", ");
        }
        // limit rows end
        if (limitRows>=0)
        {   // add limitRows and skipRows constraints
            buf.append(") row_ WHERE rownum<=");
            buf.append(usePreparedStatements ? "?" : String.valueOf(skipRows+limitRows));
            if (skipRows>0)
            {   // add skip rows
                buf.append(") WHERE rownum_>");
                buf.append(usePreparedStatements ? "?" : String.valueOf(skipRows));
            }
        }
        completeParamUsage();
    }

    @Override
    public Object[] getParamValues()
    {
        Object[] params = super.getParamValues();
        if (limitRows<0 || !isPreparedStatementsEnabled())
            return params;
        // add limit and skip params
        int newSize = (params!=null ? params.length : 0)+(skipRows>0 ? 2 : 1);
        Object[] newParams = new Object[newSize];
        // copy params
        for (int i=0; params!=null && i<params.length; i++)
            newParams[i]=params[i];
        // set skip
        if (skipRows>0)
            newParams[--newSize]=skipRows;
        // set limit
        newParams[--newSize]=skipRows+limitRows;    
        return newParams;
    }

    @Override
    protected void addUpdateForTable(StringBuilder buf, DBRowSet table)
    {
        // Optimizer Hint
        long context = CTX_FULLNAME;
        if (StringUtils.isNotEmpty(optimizerHint))
        {   // Append an optimizer hint to the select statement e.g. SELECT /*+ RULE */
            buf.append("/*+ ").append(optimizerHint).append(" */ ");
            // Append alias (if necessary)
            if (optimizerHint.contains(table.getAlias()))
                context |= CTX_ALIAS;
        }
        // table
        table.addSQL(buf, context);
        // Simple Statement
        context = CTX_NAME | CTX_VALUE;
        // Set Expressions
        buf.append("\r\nSET ");
        addListExpr(buf, set, context, ", ");
        // Add Where
        addWhere(buf, context);
    }
    
    @Override
    protected void addUpdateWithJoins(StringBuilder buf, DBRowSet table)
    {
        // The update table
        DBColumn[] keyColumns = table.getKeyColumns();
        if (keyColumns==null || keyColumns.length==0)
            throw new NoPrimaryKeyException(table);
        // Generate Merge expression
        buf.setLength(0);
        buf.append("MERGE INTO ");
        table.addSQL(buf, CTX_FULLNAME|CTX_ALIAS);
        // Using
        buf.append("\r\nUSING (");
        // Add set expressions
        List<DBColumnExpr> using = new ArrayList<DBColumnExpr>();
        // Add key columns
        for (DBColumn col : keyColumns)
            using.add(col);
        // Select Set-Expressions
        List<DBSetExpr> mergeSet = new ArrayList<DBSetExpr>(set.size());   
        for (DBSetExpr sex : set)
        {   // Select set expressions
            Object val = sex.getValue();
            if (val instanceof DBColumnExpr)
            {
                DBColumnExpr expr = ((DBColumnExpr)val);
                if (!(expr instanceof DBColumn) && !(expr instanceof DBAliasExpr))
                {   // rename column
                    String name = "COL_"+String.valueOf(mergeSet.size());
                    expr = expr.as(name);
                }
                // select
                using.add(expr);
                // Name
                DBValueExpr NAME_EXPR = getDatabase().getValueExpr("q0."+expr.getName(), DataType.UNKNOWN);
                mergeSet.add(sex.getColumn().to(NAME_EXPR));
            }
            else
            {   // add original
                mergeSet.add(sex);
            }
        }
        // Add select
        buf.append("SELECT ");
        addListExpr(buf, using, CTX_ALL, ", ");
        // From clause
        addFrom(buf);
        // Add Where
        addWhere(buf);
        // Add Grouping
        addGrouping(buf);
        // on
        buf.append(") q0\r\nON (");
        for (DBColumn col : keyColumns)
        {   // compare 
            buf.append(" q0.");
            col.addSQL(buf, CTX_NAME);
            buf.append("=");
            buf.append(table.getAlias());
            buf.append(".");
            col.addSQL(buf, CTX_NAME);
        }
        // Set Expressions
        buf.append(")\r\nWHEN MATCHED THEN UPDATE ");
        buf.append("\r\nSET ");
        addListExpr(buf, mergeSet, CTX_DEFAULT, ", ");
    }
    
    /**
     * Creates an Oracle specific delete statement.
     * @return the delete SQL-Command
     */
    
    @Override
    protected void addDeleteForTable(StringBuilder buf, DBRowSet table)
    {
        if (StringUtils.isNotEmpty(optimizerHint))
        {   // Append an optimizer hint to the select statement e.g. SELECT /*+ RULE */
            buf.append("/*+ ").append(optimizerHint).append(" */ ");
        }
        super.addDeleteForTable(buf, table);
    }
    
    @Override
    protected void addDeleteWithJoins(StringBuilder buf, DBRowSet table)
    {
        if (StringUtils.isNotEmpty(optimizerHint))
        {   // Append an optimizer hint to the select statement e.g. SELECT /*+ RULE */
            buf.append("/*+ ").append(optimizerHint).append(" */ ");
        }
        super.addDeleteWithJoins(buf, table);
    }

}