import {MapUtils as MapUtils2} from "./MapUtils";
import {SetUtils as SetUtils2} from "./SetUtils";
import {CoreType} from "./Type";
export class ArrayUtils {
  static min(array) {
    let min = array[0];
    for (let element of array) {
      if (element < min) {
        min = element;
      }
    }
    return min;
  }
  static max(array) {
    let min = array[0];
    for (let element of array) {
      if (element > min) {
        min = element;
      }
    }
    return min;
  }
  static sum(array) {
    let sum = 0;
    for (let element of array) {
      sum += element;
    }
    return sum;
  }
  static compact(array) {
    const newArray = [];
    for (let elem of array) {
      if (elem != null) {
        newArray.push(elem);
      }
    }
    return newArray;
  }
  static uniq(array) {
    const tmpSet = new Set();
    for (let elem of array) {
      tmpSet.add(elem);
    }
    const newArray = new Array(tmpSet.size);
    let i = 0;
    tmpSet.forEach((elem) => {
      newArray[i] = elem;
      i++;
    });
    return newArray;
  }
  static chunk(array, chunkSize) {
    const newArray = [];
    let newSubArray = [];
    newArray.push(newSubArray);
    for (let i = 0; i < array.length; i++) {
      if (newSubArray.length == chunkSize) {
        newSubArray = [];
        newArray.push(newSubArray);
      }
      newSubArray.push(array[i]);
    }
    return newArray;
  }
  static union(array0, array1) {
    const newArray = [];
    const unionSet = SetUtils2.union(this.toSet(array0), this.toSet(array1));
    unionSet.forEach((val) => newArray.push(val));
    return newArray;
  }
  static intersection(array0, array1) {
    const newArray = [];
    const intersectionSet = SetUtils2.intersection(this.toSet(array0), this.toSet(array1));
    intersectionSet.forEach((val) => newArray.push(val));
    return newArray;
  }
  static difference(array0, array1) {
    const newArray = [];
    const differenceSet = SetUtils2.difference(this.toSet(array0), this.toSet(array1));
    differenceSet.forEach((val) => newArray.push(val));
    return newArray;
  }
  static toSet(array) {
    const set = new Set();
    for (let elem of array) {
      set.add(elem);
    }
    return set;
  }
  static isEqual(array0, array1) {
    if (array0.length != array1.length) {
      return false;
    }
    const count = array0.length;
    for (let i = 0; i < count; i++) {
      if (array0[i] != array1[i]) {
        return false;
      }
    }
    return true;
  }
  static sortBy(array, callback) {
    if (array.length == 0) {
      return [];
    }
    const elementsByValue = new Map();
    const valuesSet = new Set();
    for (let elem of array) {
      const value = callback(elem);
      valuesSet.add(value);
      MapUtils2.push_on_array_at_entry(elementsByValue, value, elem);
    }
    const values = new Array(valuesSet.size);
    let i = 0;
    valuesSet.forEach((value) => {
      values[i] = value;
      i++;
    });
    if (CoreType.isString(values[0])) {
      values.sort();
    } else {
      values.sort((a, b) => a - b);
    }
    const sorted_elements = new Array(array.length);
    i = 0;
    for (let value of values) {
      const elements_for_value = elementsByValue.get(value);
      if (elements_for_value) {
        for (let element of elements_for_value) {
          sorted_elements[i] = element;
          i++;
        }
      }
    }
    return sorted_elements;
  }
  static range(start, end, step = 1) {
    if (end == null) {
      end = start;
      start = 0;
    }
    const length = Math.floor((end - start) / step);
    const array = new Array(length);
    for (let i = 0; i < array.length; i++) {
      array[i] = start + i * step;
    }
    return array;
  }
}
