/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.objects;

import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;

/**
 * NativeArrayBuffer - ArrayBuffer as described in the JS typed
 * array spec
 */
@ScriptClass("ArrayBuffer")
public final class NativeArrayBuffer extends ScriptObject {
    private final ByteBuffer nb;

    // initialized by nasgen
    private static PropertyMap $nasgenmap$;

    /**
     * Constructor
     * @param nb native byte buffer to wrap
     * @param global global instance
     */
    protected NativeArrayBuffer(final ByteBuffer nb, final Global global) {
        super(global.getArrayBufferPrototype(), $nasgenmap$);
        this.nb = nb;
    }

    /**
     * Constructor
     * @param nb native byte buffer to wrap
     */
    protected NativeArrayBuffer(final ByteBuffer nb) {
        this(nb, Global.instance());
    }

    /**
     * Constructor
     * @param byteLength byteLength for buffer
     */
    protected NativeArrayBuffer(final int byteLength) {
        this(ByteBuffer.allocateDirect(byteLength));
    }

    /**
     * Clone constructor
     * Used only for slice
     * @param other original buffer
     * @param begin begin byte index
     * @param end   end byte index
     */
    protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
        this(cloneBuffer(other.getNioBuffer(), begin, end));
    }

    /**
     * Constructor
     * @param newObj is this invoked with new
     * @param self   self reference
     * @param args   arguments to constructor
     * @return new NativeArrayBuffer
     */
    @Constructor(arity = 1)
    public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
        if (!newObj) {
            throw typeError("constructor.requires.new", "ArrayBuffer");
        }

        if (args.length == 0) {
            return new NativeArrayBuffer(0);
        }

        return new NativeArrayBuffer(JSType.toInt32(args[0]));
    }

    private static ByteBuffer cloneBuffer(final ByteBuffer original, final int begin, final int end) {
        final ByteBuffer clone = ByteBuffer.allocateDirect(original.capacity());
        original.rewind();//copy from the beginning
        clone.put(original);
        original.rewind();
        clone.flip();
        clone.position(begin);
        clone.limit(end);
        return clone.slice();
    }

    ByteBuffer getNioBuffer() {
        return nb;
    }

    @Override
    public String getClassName() {
        return "ArrayBuffer";
    }

    /**
     * Byte length for native array buffer
     * @param self native array buffer
     * @return byte length
     */
    @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
    public static int byteLength(final Object self) {
        return ((NativeArrayBuffer)self).getByteLength();
    }

    /**
     * Returns true if an object is an ArrayBufferView
     *
     * @param self self
     * @param obj  object to check
     *
     * @return true if obj is an ArrayBufferView
     */
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    public static boolean isView(final Object self, final Object obj) {
        return obj instanceof ArrayBufferView;
    }

    /**
     * Slice function
     * @param self   native array buffer
     * @param begin0 start byte index
     * @param end0   end byte index
     * @return new array buffer, sliced
     */
    @Function(attributes = Attribute.NOT_ENUMERABLE)
    public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
        final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
        final int               byteLength  = arrayBuffer.getByteLength();
        final int               begin       = adjustIndex(JSType.toInt32(begin0), byteLength);
        final int               end         = adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : byteLength, byteLength);
        return new NativeArrayBuffer(arrayBuffer, begin, Math.max(end, begin));
    }

    /**
     * Specialized slice function
     * @param self   native array buffer
     * @param begin  start byte index
     * @param end    end byte index
     * @return new array buffer, sliced
     */
    @SpecializedFunction
    public static Object slice(final Object self, final int begin, final int end) {
        final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
        final int byteLength  = arrayBuffer.getByteLength();
        return new NativeArrayBuffer(arrayBuffer, adjustIndex(begin, byteLength), Math.max(adjustIndex(end, byteLength), begin));
    }

    /**
     * Specialized slice function
     * @param self   native array buffer
     * @param begin  start byte index
     * @return new array buffer, sliced
     */
    @SpecializedFunction
    public static Object slice(final Object self, final int begin) {
        return slice(self, begin, ((NativeArrayBuffer)self).getByteLength());
    }

    /**
     * If index is negative, it refers to an index from the end of the array, as
     * opposed to from the beginning. The index is clamped to the valid index
     * range for the array.
     *
     * @param index  The index.
     * @param length The length of the array.
     * @return valid index index in the range [0, length).
     */
    static int adjustIndex(final int index, final int length) {
        return index < 0 ? clamp(index + length, length) : clamp(index, length);
    }

    /**
     * Clamp index into the range [0, length).
     */
    private static int clamp(final int index, final int length) {
        if (index < 0) {
            return 0;
        } else if (index > length) {
            return length;
        }
        return index;
    }

    int getByteLength() {
        return nb.limit();
    }

    ByteBuffer getBuffer() {
       return nb;
    }

    ByteBuffer getBuffer(final int offset) {
        return (ByteBuffer)nb.duplicate().position(offset);
    }

    ByteBuffer getBuffer(final int offset, final int length) {
        return (ByteBuffer)getBuffer(offset).limit(length);
    }
}
