/*
 * Copyright 2009-2010 by The Regents of the University of California
 * Licensed 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 from
 * 
 *     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 edu.uci.ics.hyracks.storage.am.common.impls;

import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.storage.am.common.api.ICursorInitialState;
import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;

public class TreeIndexDiskOrderScanCursor implements ITreeIndexCursor {

    private int tupleIndex = 0;
    private int fileId = -1;
    private int currentPageId = -1;
    private int maxPageId = -1;
    private ICachedPage page = null;
    private IBufferCache bufferCache = null;

    private final ITreeIndexFrame frame;
    private final ITreeIndexTupleReference frameTuple;

    public TreeIndexDiskOrderScanCursor(ITreeIndexFrame frame) {
        this.frame = frame;
        this.frameTuple = frame.createTupleReference();
    }

    @Override
    public void close() throws HyracksDataException {
        page.releaseReadLatch();
        bufferCache.unpin(page);
        page = null;
    }

    @Override
    public ITreeIndexTupleReference getTuple() {
        return frameTuple;
    }

    @Override
    public ICachedPage getPage() {
        return page;
    }

    private boolean positionToNextLeaf(boolean skipCurrent) throws HyracksDataException {
        while ((frame.getLevel() != 0 || skipCurrent || frame.getTupleCount() == 0) && (currentPageId <= maxPageId)) {
            currentPageId++;

            page.releaseReadLatch();
            bufferCache.unpin(page);

            ICachedPage nextPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), false);
            nextPage.acquireReadLatch();

            page = nextPage;
            frame.setPage(page);
            tupleIndex = 0;
            skipCurrent = false;
        }
        if (currentPageId <= maxPageId) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean hasNext() throws HyracksDataException {
        if (currentPageId > maxPageId) {
            return false;
        }
        if (tupleIndex >= frame.getTupleCount()) {
            boolean nextLeafExists = positionToNextLeaf(true);
            if (nextLeafExists) {
                frameTuple.resetByTupleIndex(frame, tupleIndex);
                return true;
            } else {
                return false;
            }
        }
        frameTuple.resetByTupleIndex(frame, tupleIndex);
        return true;
    }

    @Override
    public void next() throws HyracksDataException {
        tupleIndex++;
    }

    @Override
    public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException {
        // in case open is called multiple times without closing
        if (page != null) {
            page.releaseReadLatch();
            bufferCache.unpin(page);
        }
        page = initialState.getPage();
        tupleIndex = 0;
        frame.setPage(page);
        positionToNextLeaf(false);
    }

    @Override
    public void reset() {
        tupleIndex = 0;
        currentPageId = -1;
        maxPageId = -1;
        page = null;
    }

    @Override
    public void setBufferCache(IBufferCache bufferCache) {
        this.bufferCache = bufferCache;
    }

    @Override
    public void setFileId(int fileId) {
        this.fileId = fileId;
    }

    public void setCurrentPageId(int currentPageId) {
        this.currentPageId = currentPageId;
    }

    public void setMaxPageId(int maxPageId) {
        this.maxPageId = maxPageId;
    }

    @Override
    public boolean exclusiveLatchNodes() {
        return false;
    }
}
