import type { UpEntry } from "upend";

export type SortKeys = { [key: string]: string[] };

export function sortByValue(entries: UpEntry[], sortKeys: SortKeys): void {
  entries.sort((aEntry, bEntry) => {
    if (aEntry.value.t === "Number" && bEntry.value.t === "Number") {
      return bEntry.value.c - aEntry.value.c;
    }

    if (
      !sortKeys[aEntry.value.c]?.length ||
      !sortKeys[bEntry.value.c]?.length
    ) {
      if (
        Boolean(sortKeys[aEntry.value.c]?.length) &&
        !sortKeys[bEntry.value.c]?.length
      ) {
        return -1;
      } else if (
        !sortKeys[aEntry.value.c]?.length &&
        Boolean(sortKeys[bEntry.value.c]?.length)
      ) {
        return 1;
      } else {
        return String(aEntry.value.c).localeCompare(
          String(bEntry.value.c),
          undefined,
          { numeric: true, sensitivity: "base" }
        );
      }
    } else {
      return sortKeys[aEntry.value.c][0].localeCompare(
        sortKeys[bEntry.value.c][0],
        undefined,
        { numeric: true, sensitivity: "base" }
      );
    }
  });
}

export function sortByValueLength(entries: UpEntry[]) {
  entries.sort((aEntry, bEntry) => {
    return String(aEntry.value.c).length - String(bEntry.value.c).length;
  });
}

export function sortByAttribute(entries: UpEntry[], sortKeys: SortKeys): void {
  entries.sort((aEntry, bEntry) => {
    const aResolved = (sortKeys[aEntry.attribute] || [])[0] || aEntry.attribute;
    const bResolved = (sortKeys[bEntry.attribute] || [])[0] || bEntry.attribute;
    return aResolved.localeCompare(bResolved);
  });
}

export function sortByEntity(entries: UpEntry[], sortKeys: SortKeys): void {
  entries.sort((aEntry, bEntry) => {
    if (!sortKeys[aEntry.entity]?.length || !sortKeys[bEntry.entity]?.length) {
      if (
        Boolean(sortKeys[aEntry.entity]?.length) &&
        !sortKeys[bEntry.entity]?.length
      ) {
        return -1;
      } else if (
        !sortKeys[aEntry.entity]?.length &&
        Boolean(sortKeys[bEntry.entity]?.length)
      ) {
        return 1;
      } else {
        return aEntry.entity.localeCompare(bEntry.entity);
      }
    } else {
      return sortKeys[aEntry.entity][0].localeCompare(
        sortKeys[bEntry.entity][0]
      );
    }
  });
}

export function defaultEntitySort(
  entries: UpEntry[],
  sortKeys: SortKeys
): UpEntry[] {
  const result = entries.concat();
  sortByValue(result, sortKeys);
  sortByValueLength(result);
  sortByAttribute(result, sortKeys);
  sortByEntity(result, sortKeys);
  return result;
}

export function entityValueSort(
  entries: UpEntry[],
  sortKeys: SortKeys
): UpEntry[] {
  const result = entries.concat();
  sortByEntity(result, sortKeys);
  sortByAttribute(result, sortKeys);
  sortByValueLength(result);
  sortByValue(result, sortKeys);
  return result;
}
