// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/**
 * Operations on collections.
 */
library dart.pkg.collection.algorithms;

import "dart:math" show Random;

/** Version of [binarySearch] optimized for comparable keys */
int _comparableBinarySearch(List<Comparable> list, Comparable value) {
  int min = 0;
  int max = list.length;
  while (min < max) {
    int mid = min + ((max - min) >> 1);
    var element = list[mid];
    int comp = element.compareTo(value);
    if (comp == 0) return mid;
    if (comp < 0) {
      min = mid + 1;
    } else {
      max = mid;
    }
  }
  return -1;
}

/**
 * Returns a position of the [value] in [sortedList], if it is there.
 *
 * If the list isn't sorted according to the [compare] function, the result
 * is unpredictable.
 *
 * If [compare] is omitted, it defaults to calling [Comparable.compareTo] on
 * the objects.
 *
 * Returns -1 if [value] is not in the list by default.
 */
int binarySearch(List sortedList, value, { int compare(a, b) }) {
  if (compare == null) {
    return _comparableBinarySearch(sortedList, value);
  }
  int min = 0;
  int max = sortedList.length;
  while (min < max) {
    int mid = min + ((max - min) >> 1);
    var element = sortedList[mid];
    int comp = compare(element, value);
    if (comp == 0) return mid;
    if (comp < 0) {
      min = mid + 1;
    } else {
      max = mid;
    }
  }
  return -1;
}

/** Version of [lowerBound] optimized for comparable keys */
int _comparableLowerBound(List<Comparable> list, Comparable value) {
  int min = 0;
  int max = list.length;
  while (min < max) {
    int mid = min + ((max - min) >> 1);
    var element = list[mid];
    int comp = element.compareTo(value);
    if (comp < 0) {
      min = mid + 1;
    } else {
      max = mid;
    }
  }
  return min;
}

/**
 * Returns the first position in [sortedList] that does not compare less than
 * [value].
 *
 * If the list isn't sorted according to the [compare] function, the result
 * is unpredictable.
 *
 * If [compare] is omitted, it defaults to calling [Comparable.compareTo] on
 * the objects.
 *
 * Returns [sortedList.length] if all the items in [sortedList] compare less
 * than [value].
 */
int lowerBound(List sortedList, value, { int compare(a, b) }) {
  if (compare == null) {
    return _comparableLowerBound(sortedList, value);
  }
  int min = 0;
  int max = sortedList.length;
  while (min < max) {
    int mid = min + ((max - min) >> 1);
    var element = sortedList[mid];
    int comp = compare(element, value);
    if (comp < 0) {
      min = mid + 1;
    } else {
      max = mid;
    }
  }
  return min;
}

/**
 * Shuffles a list randomly.
 *
 * A sub-range of a list can be shuffled by providing [start] and [end].
 */
void shuffle(List list, [int start = 0, int end = null]) {
  Random random = new Random();
  if (end == null) end = list.length;
  int length = end - start;
  while (length > 1) {
    int pos = random.nextInt(length);
    length--;
    var tmp1 = list[start + pos];
    list[start + pos] = list[start + length];
    list[start + length] = tmp1;
  }
}


/**
 * Reverses a list, or a part of a list, in-place.
 */
void reverse(List list, [int start = 0, int end = null]) {
  if (end == null) end = list.length;
  _reverse(list, start, end);
}

// Internal helper function that assumes valid arguments.
void _reverse(List list, int start, int end) {
  for (int i = start, j = end - 1; i < j; i++, j--) {
    var tmp = list[i];
    list[i] = list[j];
    list[j] = tmp;
  }
}

/**
 * Sort a list using insertion sort.
 *
 * Insertion sort is a simple sorting algorithm. For `n` elements it does on
 * the order of `n * log(n)` comparisons but up to `n` squared moves. The
 * sorting is performed in-place, without using extra memory.
 *
 * For short lists the many moves have less impact than the simple algorithm,
 * and it is often the favored sorting algorithm for short lists.
 *
 * This insertion sort is stable: Equal elements end up in the same order
 * as they started in.
 */
void insertionSort(List list,
                   { int compare(a, b),
                     int start: 0,
                     int end: null }) {
  // If the same method could have both positional and named optional
  // parameters, this should be (list, [start, end], {compare}).
  if (end == null) end = list.length;
  if (compare == null) compare = Comparable.compare;
  _insertionSort(list, compare, start, end, start + 1);
}

/**
 * Internal helper function that assumes arguments correct.
 *
 * Assumes that the elements up to [sortedUntil] (not inclusive) are
 * already sorted. The [sortedUntil] values should always be at least
 * `start + 1`.
 */
void _insertionSort(List list, int compare(a, b), int start, int end,
                    int sortedUntil) {
  for (int pos = sortedUntil; pos < end; pos++) {
    int min = start;
    int max = pos;
    var element = list[pos];
    while (min < max) {
      int mid = min + ((max - min) >> 1);
      int comparison = compare(element, list[mid]);
      if (comparison < 0) {
        max = mid;
      } else {
        min = mid + 1;
      }
    }
    list.setRange(min + 1, pos + 1, list, min);
    list[min] = element;
  }
}

/** Limit below which merge sort defaults to insertion sort. */
const int _MERGE_SORT_LIMIT = 32;

/**
 * Sorts a list, or a range of a list, using the merge sort algorithm.
 *
 * Merge-sorting works by splitting the job into two parts, sorting each
 * recursively, and then merging the two sorted parts.
 *
 * This takes on the order of `n * log(n)` comparisons and moves to sort
 * `n` elements, but requires extra space of about the same size as the list
 * being sorted.
 *
 * This merge sort is stable: Equal elements end up in the same order
 * as they started in.
 */
void mergeSort(List list, {int start: 0, int end: null, int compare(a, b)}) {
  if (end == null) end = list.length;
  if (compare == null) compare = Comparable.compare;
  int length = end - start;
  if (length < 2) return;
  if (length < _MERGE_SORT_LIMIT) {
    _insertionSort(list, compare, start, end, start + 1);
    return;
  }
  // Special case the first split instead of directly calling
  // _mergeSort, because the _mergeSort requires its target to
  // be different from its source, and it requires extra space
  // of the same size as the list to sort.
  // This split allows us to have only half as much extra space,
  // and it ends up in the original place.
  int middle = start + ((end - start) >> 1);
  int firstLength = middle - start;
  int secondLength = end - middle;
  // secondLength is always the same as firstLength, or one greater.
  List scratchSpace = new List(secondLength);
  _mergeSort(list, compare, middle, end, scratchSpace, 0);
  int firstTarget = end - firstLength;
  _mergeSort(list, compare, start, middle, list, firstTarget);
  _merge(compare,
         list, firstTarget, end,
         scratchSpace, 0, secondLength,
         list, start);
}

/**
 * Performs an insertion sort into a potentially different list than the
 * one containing the original values.
 *
 * It will work in-place as well.
 */
void _movingInsertionSort(List list, int compare(a, b), int start, int end,
                          List target, int targetOffset) {
  int length = end - start;
  if (length == 0) return;
  target[targetOffset] = list[start];
  for (int i = 1; i < length; i++) {
    var element = list[start + i];
    int min = targetOffset;
    int max = targetOffset + i;
    while (min < max) {
      int mid = min + ((max - min) >> 1);
      if (compare(element, target[mid]) < 0) {
        max = mid;
      } else {
        min = mid + 1;
      }
    }
    target.setRange(min + 1, targetOffset + i + 1,
                    target, min);
    target[min] = element;
  }
}

/**
 * Sorts [list] from [start] to [end] into [target] at [targetOffset].
 *
 * The `target` list must be able to contain the range from `start` to `end`
 * after `targetOffset`.
 *
 * Allows target to be the same list as [list], as long as it's not
 * overlapping the `start..end` range.
 */
void _mergeSort(List list, int compare(a, b), int start, int end,
                List target, int targetOffset) {
  int length = end - start;
  if (length < _MERGE_SORT_LIMIT) {
    _movingInsertionSort(list, compare, start, end, target, targetOffset);
    return;
  }
  int middle = start + (length >> 1);
  int firstLength = middle - start;
  int secondLength = end - middle;
  // Here secondLength >= firstLength (differs by at most one).
  int targetMiddle = targetOffset + firstLength;
  // Sort the second half into the end of the target area.
  _mergeSort(list, compare, middle, end,
             target, targetMiddle);
  // Sort the first half into the end of the source area.
  _mergeSort(list, compare, start, middle,
             list, middle);
  // Merge the two parts into the target area.
  _merge(compare,
         list, middle, middle + firstLength,
         target, targetMiddle, targetMiddle + secondLength,
         target, targetOffset);
}

/**
 * Merges two lists into a target list.
 *
 * One of the input lists may be positioned at the end of the target
 * list.
 *
 * For equal object, elements from [firstList] are always preferred.
 * This allows the merge to be stable if the first list contains elements
 * that started out earlier than the ones in [secondList]
 */
void _merge(int compare(a, b),
            List firstList, int firstStart, int firstEnd,
            List secondList, int secondStart, int secondEnd,
            List target, int targetOffset) {
  // No empty lists reaches here.
  assert(firstStart < firstEnd);
  assert(secondStart < secondEnd);
  int cursor1 = firstStart;
  int cursor2 = secondStart;
  var firstElement = firstList[cursor1++];
  var secondElement = secondList[cursor2++];
  while (true) {
    if (compare(firstElement, secondElement) <= 0) {
      target[targetOffset++] = firstElement;
      if (cursor1 == firstEnd) break;  // Flushing second list after loop.
      firstElement = firstList[cursor1++];
    } else {
      target[targetOffset++] = secondElement;
      if (cursor2 != secondEnd) {
        secondElement = secondList[cursor2++];
        continue;
      }
      // Second list empties first. Flushing first list here.
      target[targetOffset++] = firstElement;
      target.setRange(targetOffset, targetOffset + (firstEnd - cursor1),
          firstList, cursor1);
      return;
    }
  }
  // First list empties first. Reached by break above.
  target[targetOffset++] = secondElement;
  target.setRange(targetOffset, targetOffset + (secondEnd - cursor2),
      secondList, cursor2);
}
