/*
 * Copyright 2010 Google Inc.
 *
 * 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 at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package elemental.js.util;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayInteger;

import elemental.util.ArrayOfInt;
import elemental.util.CanCompareInt;

/**
 * JavaScript implementation of {@link ArrayOfInt}.
 */
@Deprecated
public final class JsArrayOfInt extends JsArrayInteger implements ArrayOfInt {

  /**
   * Create a new empty instance.
   */
  public static JsArrayOfInt create() {
    return JavaScriptObject.createArray().cast();
  }

  protected JsArrayOfInt() {
  }

  public native JsArrayOfInt concat(ArrayOfInt values) /*-{
    return this.concat(values);
  }-*/;

  public boolean contains(int value) {
    return indexOf(value) != -1;
  }

  public native int indexOf(int value) /*-{
    return this.indexOf(value);
  }-*/;

  public native void insert(int index, int value) /*-{
    this.splice(index, 0, value);
  }-*/;

  public boolean isEmpty() {
    return JsArrayOf.isEmpty(this);
  }

  public native boolean isSet(int index) /*-{
    return this[index] !== undefined;
  }-*/;

  public native int peek() /*-{
    return this[this.length - 1];
  }-*/;

  public native int pop() /*-{
    return this.pop();
  }-*/;

  public void remove(int value) {
    final int index = indexOf(value);
    if (index != -1) {
      splice(index, 1);
    }
  }

  public void removeByIndex(int index) {
    splice(index, 1);
  }

  public native void sort() /*-{
    this.sort();
  }-*/;

  public native void sort(CanCompareInt comparator) /*-{
    this.sort(function(a, b) {
      return comparator.@elemental.util.CanCompareInt::compare(II)(a, b);
    });
  }-*/;

  public JsArrayOfInt splice(int index, int count) {
    return JsArrayOf.splice(this, index, count);
  }
}
