/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.queries;

import java.util.*;
import java.sql.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.databaseaccess.*;

public class ScrollableCursor extends Cursor implements ListIterator {
    protected transient Object nextObject;
    protected transient Object previousObject;
    /** Store the previous row, for 1-m joining. */
    protected AbstractRecord previousRow;
    /** Internal flag indicating if the end of the cursor has been reached */
    protected boolean atEndOfCursor = false;

    /**
     * INTERNAL:
     * Default constructor.
     */
    public ScrollableCursor() {
        super();
    }

    /**
     * INTERNAL:
     * constructor.
     */
    public ScrollableCursor(DatabaseCall call, ScrollableCursorPolicy policy) {
        super(call, policy);
        setPosition(-1);
    }

    /**
     * PUBLIC:
     * Moves the cursor to the given row number in the result set
     */
    public boolean absolute(int rows) throws DatabaseException {
        clearNextAndPrevious();
        try {
            boolean suceeded = false;
            int initiallyConforming = this.objectCollection.size();
            if ((rows >= 0) && (rows <= initiallyConforming)) {
                this.resultSet.beforeFirst();
                setPosition(rows);
                return true;
            } else if (rows > initiallyConforming) {
                suceeded = this.resultSet.absolute(rows - initiallyConforming);
                if (suceeded) {
                    setPosition(initiallyConforming + rows);
                } else {
                    // Must be afterLast.
                    setPosition(size() + 1);
                }
                return suceeded;
            } else {//  (rows < 0)
                // Need to know how big the result set is...
                return absolute(size() + rows);
            }
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * PUBLIC:
     * Add is not support for scrollable cursors.
     */
    @Override
    public void add(Object object) throws QueryException {
        QueryException.invalidOperation("add");
    }

    /**
     * PUBLIC:
     * Moves the cursor to the end of the result set, just after the last row.
     */
    public void afterLast() throws DatabaseException {
        clearNextAndPrevious();
        try {
            this.resultSet.afterLast();
            setPosition(size() + 1);
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * PUBLIC:
     * Moves the cursor to the front of the result set, just before the first row
     */
    public void beforeFirst() throws DatabaseException {
        clearNextAndPrevious();
        try {
            this.resultSet.beforeFirst();
            setPosition(0);
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * INTERNAL:
     * Clear the cached next and previous object and row values.
     * This must be called whenever the cursor is re-positioned.
     */
    protected void clearNextAndPrevious() {
        this.nextObject = null;
        this.previousObject = null;
        this.nextRow = null;
        this.previousRow = null;
        this.atEndOfCursor = false;
    }

    /**
     * INTERNAL:
     * Clear only the cached next and previous object values.
     * Called by previous() and next() to maintain the cached next
     * and previous row values.
     */
    protected void clearNextAndPreviousObject() {
        this.nextObject = null;
        this.previousObject = null;
    }

    /**
     * PUBLIC:
     * Retrieves the current row index number
     */
    public int currentIndex() throws DatabaseException {
        return getPosition();
    }

    /**
     * PUBLIC:
     * Moves the cursor to the first row in the result set
     */
    public boolean first() throws DatabaseException {
        clearNextAndPrevious();
        try {
            if (this.objectCollection.size() > 0) {
                setPosition(1);
                this.resultSet.beforeFirst();
                return true;
            } else {
                return this.resultSet.first();
            }
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * INTERNAL:
     * Retrieve the size of the open cursor by executing a count on the same query as the cursor.
     */
    @Override
    protected int getCursorSize() throws DatabaseException {
        if (getKnownCursorSize() != -1) {
            return getKnownCursorSize();
        }
        int currentPos = 0;

        // If afterLast getRow() will return 0!
        boolean wasAfterLast = false;

        try {
            wasAfterLast = this.resultSet.isAfterLast();
            currentPos = this.resultSet.getRow();
            this.resultSet.last();
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }

        int size = 0;
        try {
            size = this.resultSet.getRow();
            if (wasAfterLast) {// Move the cursor back to where we were before calling last()
                this.resultSet.afterLast();
            } else if (currentPos == 0) {
                this.resultSet.beforeFirst();
            } else {
                this.resultSet.absolute(currentPos);
            }
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }

        return size;
    }

    protected int getKnownCursorSize() {
        if (size == -1) {
            return size;
        } else {
            return size - this.objectCollection.size();
        }
    }

    protected Object getNextObject() {
        return nextObject;
    }

    /**
     * PUBLIC:
     * Retrieves the current cursor position (current row).  The first row is number 1, the second number 2, and so on.
     * Unlike java.sql.ResultSet.getRow(), 0 is not returned if afterLast.
     * Instead size() + 1 is returned.
     * @return the current row number; 0 if there is no current row
     * @exception DatabaseException if a database access error occurs
     */
    @Override
    public int getPosition() throws DatabaseException {
        try {
            if (this.position == -1) {
                this.position = this.resultSet.getRow();
                if (this.position == 0) {
                    // This could mean either beforeFirst or afterLast!
                    if (isAfterLast()) {
                        this.position = size() + 1;
                    }
                } else {
                    this.position += this.objectCollection.size();
                }
            }
            return this.position;
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    protected Object getPreviousObject() {
        return previousObject;
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor can move to the the next row
     */
    @Override
    public boolean hasMoreElements() throws DatabaseException {
        return hasNext();
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor can move to the the next row
     */
    @Override
    public boolean hasNext() throws DatabaseException {
        if (isClosed()) {
            return false;
        }
        loadNext();
        return (this.nextObject != null);
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor can move to the the next row
     */
    public boolean hasNextElement() throws DatabaseException {
        return hasNext();
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor can move to the the previous row
     */
    @Override
    public boolean hasPrevious() throws DatabaseException {
        if (isClosed()) {
            return false;
        }

        loadPrevious();
        return (getPreviousObject() != null);
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor is after the last row in the result set.
     */
    public boolean isAfterLast() throws DatabaseException {
        try {
            if (this.nextObject != null) {
                return false;
            }
            if ((this.objectCollection.size() > 0) && (getPosition() <= this.objectCollection.size())) {
                return false;
            }
            return this.resultSet.isAfterLast();
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor is before the first row in the result set.
     */
    public boolean isBeforeFirst() throws DatabaseException {
        if (getPreviousObject() != null) {
            return false;
        }
        return getPosition() == 0;
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor is on the first row of the result set.
     */
    public boolean isFirst() throws DatabaseException {
        if (getPreviousObject() != null) {
            return false;
        }
        try {
            if (this.objectCollection.size() > 0) {
                return getPosition() == 1;
            }
            return this.resultSet.isFirst();
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * PUBLIC:
     * Indicates whether the cursor is on the last row of the result set.
     */
    public boolean isLast() throws DatabaseException {
        if (this.nextObject != null) {
            return false;
        }
        try {
            return this.resultSet.isLast();
        } catch (UnsupportedOperationException ex) {
            // isLast() is not supported by some drivers (specifically JConnect5.0)
            // Do this the hard way instead.
            try {
                return this.resultSet.getRow() == getCursorSize();
            } catch (SQLException ex2) {
                DatabaseException commException = getAccessor().processExceptionForCommError(this.session, ex2, null);
                if (commException != null) throw commException;
                throw DatabaseException.sqlException(ex2, getAccessor(), this.session, false);
            }
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * PUBLIC:
     * Moves the cursor to the last row in the result set
     */
    public boolean last() throws DatabaseException {
        clearNextAndPrevious();
        try {
            boolean isLast = this.resultSet.last();
            if (!isLast) {
                // cursor must be empty.
                if (this.objectCollection.size() > 0) {
                    setPosition(this.objectCollection.size());
                    isLast = true;
                }
            } else {
                setSize(this.objectCollection.size() + this.resultSet.getRow());
                setPosition(size);
            }
            return isLast;
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * Load the next object
     */
    protected void loadNext() {
        if (this.nextObject == null) {
            Object next = retrieveNextObject();
            this.nextObject = next;
        }
    }

    /**
     * Load the previous object. This is used solely for scrollable cursor support
     */
    protected void loadPrevious() {
        // CR#4139
        if (this.previousObject == null) {
            this.previousObject = retrievePreviousObject();
        }
    }

    /**
     * PUBLIC:
     * This method differs slightly from conventional read() operation on a Java stream.  This
     * method return the next object in the collection rather than specifying the number of
     * bytes to be read in.
     *
     * Return the next object from the collection, if beyond the read limit read from the cursor
     * @return - next object in stream
     * @throws DatabaseException if read pass end of stream
     */
    @Override
    public Object next() throws DatabaseException, QueryException {
        loadNext();
        if (this.nextObject == null) {
            throw QueryException.readBeyondStream(this.query);
        }
        Object next = this.nextObject;
        clearNextAndPreviousObject();
        return next;
    }

    /**
     * PUBLIC:
     * This method differs slightly from conventional read() operation on a Java stream.  This
     * method returns the next number of objects in the collection in a vector.
     *
     * Return the next specified number of objects from the collection, if beyond the read limit read from the cursor
     * @param number - number of objects to be returned
     * @return - vector containing next number of objects
     * @throws DatabaseException if read pass end of stream
     */
    public List<Object> next(int number) throws DatabaseException {
        List<Object> result = new ArrayList(number);
        for (int index = 0; index < number; index++) {
            result.add(next());
        }
        return result;
    }

    /**
     * PUBLIC:
     * Return the next object from the collection, if beyond the read limit read from the cursor.
     * @return next object in stream
     */
    @Override
    public Object nextElement() throws DatabaseException, QueryException {
        return next();
    }

    /**
     * PUBLIC:
     * Retrieves the next row index (against the current row)
     */
    @Override
    public int nextIndex() throws DatabaseException {
        return currentIndex() + 1;
    }

    /**
     * PUBLIC:
     * Return the previous object from the collection.
     *
     * @return - previous object in stream
     * @throws DatabaseException if read pass first of stream
     */
    @Override
    public Object previous() throws DatabaseException, QueryException {
        loadPrevious();
        if (this.previousObject == null) {
            throw QueryException.readBeyondStream(this.query);
        }
        Object previous = this.previousObject;
        clearNextAndPreviousObject();
        return previous;
    }

    /**
     * PUBLIC:
     * Retrieves the previous row index (against the current row)
     */
    @Override
    public int previousIndex() throws DatabaseException {
        return currentIndex() - 1;
    }

    /**
     * PUBLIC:
     * Moves the cursor a relative number of rows, either positive or negative.
     * Attempting to move beyond the first/last row in the result set positions the cursor before/after the
     * the first/last row
     */
    public boolean relative(int rows) throws DatabaseException {
        clearNextAndPrevious();
        try {
            boolean suceeded = false;
            int oldPosition = getPosition();
            int newPosition = getPosition() + rows;
            int initiallyConforming = this.objectCollection.size();
            if (newPosition <= initiallyConforming) {
                setPosition(newPosition);
                if (oldPosition > initiallyConforming) {
                    this.resultSet.beforeFirst();
                }
                if (newPosition < 0) {
                    setPosition(0);
                }
                suceeded = (newPosition > 0);
            } else {
                suceeded = this.resultSet.relative(rows);
                if (!suceeded) {
                    // Must be afterLast now.
                    setPosition(size() + 1);
                } else {
                    setPosition(newPosition);
                }
            }
            return suceeded;
        } catch (SQLException exception) {
            DatabaseException commException = getAccessor().processExceptionForCommError(this.session, exception, null);
            if (commException != null) throw commException;
            throw DatabaseException.sqlException(exception, getAccessor(), this.session, false);
        }
    }

    /**
     * INTERNAL:
     * Read the next row from the result set.
     */
    @Override
    protected Object retrieveNextObject() throws DatabaseException {
        while (true) {
            int currentPosition = getPosition();
            if (currentPosition < this.objectCollection.size()) {
                this.position = currentPosition + 1;
                return this.objectCollection.get(currentPosition);
            }
            if (isClosed()) {
                return null;
            }
            AbstractRecord row = null;
            // if the end of the cursor has been reached, do not retrieve more rows
            if (!this.atEndOfCursor) {
                if (this.nextRow == null) {
                    row = getAccessor().cursorRetrieveNextRow(this.fields, this.resultSet, this.executionSession);
                } else {
                    row = this.nextRow;
                    this.nextRow = null;
                }
            }

            this.position = currentPosition + 1;  // bug 309142
            if (row == null) {
                this.atEndOfCursor = true;
                return null;
            }

            // If using 1-m joining need to fetch 1-m rows as well.
            if (this.query.isObjectLevelReadQuery() && ((ObjectLevelReadQuery)this.query).hasJoining()) {
                JoinedAttributeManager joinManager = ((ObjectLevelReadQuery)this.query).getJoinedAttributeManager();
                if (joinManager.isToManyJoin()) {
                    this.nextRow = joinManager.processDataResults(row, this, true);
                    // if the join manager returns a null next row, we are at the end of the cursor
                    if (this.nextRow == null) {
                       this.atEndOfCursor = true;
                    }
                }
            }

            Object object = buildAndRegisterObject(row);
            if (object == InvalidObject.instance) {
                continue;
            }
            return object;
        }
    }

    /**
     * INTERNAL:
     * CR#4139
     * Read the previous row from the result set. It is used solely
     * for scrollable cursor support.
     */
    protected Object retrievePreviousObject() throws DatabaseException {
        while (true) {
            int currentPosition = getPosition();
            if (currentPosition <= (this.objectCollection.size() + 1)) {
                // If at first of cursor, move cursor to beforeFirst.
                if ((currentPosition == (this.objectCollection.size() + 1)) && (!isClosed())) {
                    getAccessor().cursorRetrievePreviousRow(this.fields, this.resultSet, this.executionSession);
                }
                if (currentPosition <= 1) {
                    // Cursor can not move back further than beforeFirst.
                    this.position = 0;
                    return null;
                } else {
                    this.position = currentPosition - 1;
                    return this.objectCollection.get(this.position - 1);
                }
            }
            if (isClosed()) {
                return null;
            }
            AbstractRecord row = null;
            if (this.previousRow == null) {
                row = getAccessor().cursorRetrievePreviousRow(this.fields, this.resultSet, this.executionSession);
            } else {
                row = this.previousRow;
                this.previousRow = null;
            }

            this.position = currentPosition - 1;
            if (row == null) {
                return null;
            }

            // If using 1-m joining need to fetch 1-m rows as well.
            if (this.query.isObjectLevelReadQuery() && ((ObjectLevelReadQuery)this.query).hasJoining()) {
                JoinedAttributeManager joinManager = ((ObjectLevelReadQuery)this.query).getJoinedAttributeManager();
                if (joinManager.isToManyJoin()) {
                    this.previousRow = joinManager.processDataResults(row, this, false);
                }
            }

            Object object = buildAndRegisterObject(row);

            // keep going until find one that conforms.
            if (object == InvalidObject.instance) {
                continue;
            }
            return object;
        }
    }

    /**
     * PUBLIC:
     * Set is not supported for scrollable cursors.
     */
    @Override
    public void set(Object object) throws QueryException {
        QueryException.invalidOperation("set");
    }

    protected void setNextObject(Object nextObject) {
        this.nextObject = nextObject;
    }

    protected void setPreviousObject(Object previousObject) {
        this.previousObject = previousObject;
    }
}
