/*
 * Copyright (c) 2010, Michael Bien
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Michael Bien nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Michael Bien BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Created on Saturday, March 27 2010 11:55
 */
package com.jogamp.common.nio;

import com.jogamp.common.os.*;
import java.nio.ByteBuffer;
import java.nio.Buffer;
import java.util.HashMap;

/**
 * Hardware independent container for native pointer arrays.
 *
 * The native values (NIO direct ByteBuffer) might be 32bit or 64bit wide,
 * depending of the CPU pointer width.
 *
 * @author Michael Bien
 * @author Sven Gothel
 */
public abstract class AbstractLongBuffer extends AbstractBuffer {

    protected long[] backup;

    protected HashMap/*<aptr, buffer>*/ dataMap = new HashMap();

    static {
        NativeLibrary.ensureNativeLibLoaded();
    }

    protected AbstractLongBuffer(ByteBuffer bb, int elementSize) {
        super(bb, elementSize);

        backup = new long[capacity];
    }

    final void updateBackup() {
        for (int i = 0; i < capacity; i++) {
            backup[i] = get(i);
        }
    }

    public final boolean hasArray() {
        return true;
    }

    public final long[] array() {
        return backup;
    }

    /** Absolute get method. Get the pointer value at the given index */
    public abstract long get(int idx);

    /** Relative get method. Get the pointer value at the current position and increment the position by one. */
    public final long get() {
        long r = get(position);
        position++;
        return r;
    }

    /** 
     * Relative bulk get method. Copy the pointer values <code> [ position .. position+length [</code> 
     * to the destination array <code> [ dest[offset] .. dest[offset+length] [ </code>
     * and increment the position by <code>length</code>. */
    public final AbstractLongBuffer get(long[] dest, int offset, int length) {
        if (dest.length<offset+length) {
            throw new IndexOutOfBoundsException();
        }
        if (remaining() < length) {
            throw new IndexOutOfBoundsException();
        }
        while(length>0) {
            dest[offset++] = get(position++);
            length--;
        }
        return this;
    }

    /** Absolute put method. Put the pointer value at the given index */
    public abstract AbstractLongBuffer put(int index, long value);

    /** Relative put method. Put the pointer value at the current position and increment the position by one. */
    public final AbstractLongBuffer put(long value) {
        put(position, value);
        position++;
        return this;
    }

    /** 
     * Relative bulk put method. Put the pointer values <code> [ src[offset] .. src[offset+length] [</code> 
     * at the current position and increment the position by <code>length</code>. */
    public final AbstractLongBuffer put(long[] src, int offset, int length) {
        if (src.length<offset+length) {
            throw new IndexOutOfBoundsException();
        }
        if (remaining() < length) {
            throw new IndexOutOfBoundsException();
        }
        while(length>0) {
            put(position++, src[offset++]);
            length--;
        }
        return this;
    }

    /** 
     * Relative bulk get method. Copy the source values <code> src[position .. capacity] [</code> 
     * to this buffer and increment the position by <code>capacity-position</code>. */
    public AbstractLongBuffer put(AbstractLongBuffer src) {
        if (remaining() < src.remaining()) {
            throw new IndexOutOfBoundsException();
        }
        while (src.hasRemaining()) {
                 put(src.get()); 
        }
        return this;
    }
}