/*
 * Copyright 2015 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
 * 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 javaemul.internal;

import jsinterop.annotations.JsFunction;
import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;

/** Provides utilities to perform operations on Arrays. */
public final class ArrayHelper {

  public static final int ARRAY_PROCESS_BATCH_SIZE = 10000;

  public static <T> T[] clone(T[] array) {
    Object result = asNativeArray(array).slice();
    return ArrayStamper.stampJavaTypeInfo(result, array);
  }

  public static <T> T[] clone(T[] array, int fromIndex, int toIndex) {
    Object result = unsafeClone(array, fromIndex, toIndex);
    // array.slice doesn't expand if toIndex > array.length
    setLength(result, toIndex - fromIndex);
    return ArrayStamper.stampJavaTypeInfo(result, array);
  }

  /**
   * Unlike clone, this method returns a copy of the array that is not type marked, nor size
   * guaranteed. This is only safe for temp arrays as returned array will not do any type checks.
   */
  public static Object[] unsafeClone(Object array, int fromIndex, int toIndex) {
    return asNativeArray(array).slice(fromIndex, toIndex);
  }

  public static <T> T[] createFrom(T[] array, int length) {
    return ArrayStamper.stampJavaTypeInfo(new NativeArray(length), array);
  }

  @JsMethod(name = "Array.isArray", namespace = "<window>")
  public static native boolean isArray(Object o);

  public static int getLength(Object array) {
    return asNativeArray(array).length;
  }

  public static void setLength(Object array, int length) {
    asNativeArray(array).length = length;
  }

  public static void push(Object[] array, Object o) {
    asNativeArray(array).push(o);
  }

  public static void removeFrom(Object[] array, int index, int deleteCount) {
    asNativeArray(array).splice(index, deleteCount);
  }

  public static void insertTo(Object[] array, int index, Object value) {
    asNativeArray(array).splice(index, 0, value);
  }

  public static void insertTo(Object[] array, int index, Object[] values) {
    copy(values, 0, array, index, values.length, false);
  }

  public static void copy(Object array, int srcOfs, Object dest, int destOfs, int len) {
    copy(array, srcOfs, dest, destOfs, len, true);
  }

  private static void copy(
      Object src, int srcOfs, Object dest, int destOfs, int len, boolean overwrite) {
    /*
     * Array.prototype.splice is not used directly to overcome the limits imposed to the number of
     * function parameters by browsers.
     */

    if (src == dest) {
      // copying to the same array, make a copy first
      src = unsafeClone(src, srcOfs, srcOfs + len);
      srcOfs = 0;
    }
    NativeArray destArray = asNativeArray(dest);
    for (int batchStart = srcOfs, end = srcOfs + len; batchStart < end;) {
      // increment in block
      int batchEnd = Math.min(batchStart + ARRAY_PROCESS_BATCH_SIZE, end);
      len = batchEnd - batchStart;
      Object[] spliceArgs = unsafeClone(src, batchStart, batchEnd);
      asNativeArray(spliceArgs).splice(0, 0, (double) destOfs, (double) (overwrite ? len : 0));
      getSpliceFunction().apply(destArray, spliceArgs);
      batchStart = batchEnd;
      destOfs += len;
    }
  }

  @JsType(isNative = true, name = "Function", namespace = "<window>")
  private static class NativeFunction {
    public native String apply(Object thisContext, Object[] argsArray);
  }

  @JsProperty(name = "Array.prototype.splice", namespace = "<window>")
  private static native NativeFunction getSpliceFunction();

  /** Compare function for sort. */
  @JsFunction
  public interface CompareFunction {
    double compare(Object d1, Object d2);
  }

  public static void sort(Object array, CompareFunction fn) {
    asNativeArray(array).sort(fn);
  }

  private static NativeArray asNativeArray(Object array) {
    return JsUtils.uncheckedCast(array);
  }

  @JsType(isNative = true, name = "Array", namespace = "<window>")
  private static class NativeArray {
    int length;

    NativeArray(int length) {}

    native void push(Object item);

    native Object[] slice();

    native Object[] slice(int fromIndex, int toIndex);

    native void splice(int index, int deleteCount, Object... value);

    native <T> void sort(CompareFunction compareFunction);
  }

  private ArrayHelper() {}
}

