/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import {fireAlert} from './event-util';

/**
 * @fileoverview Functions in this file contains some widely used
 * code patterns. If you noticed a repeated code and none of the existing util
 * files are appropriate for it - you can wrap the code in a function and put it
 * here. If you notice that several functions can be group together - create
 * a separate util file for them.
 */

/**
 * Wrapper for the Object.prototype.hasOwnProperty method
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function hasOwnProperty(obj: any, prop: PropertyKey) {
  // Typescript rules don't allow to use obj.hasOwnProperty directly
  return Object.prototype.hasOwnProperty.call(obj, prop);
}

// TODO(TS): move to common types once we have type utils
//  Required for constructor signature.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Constructor<T> = new (...args: any[]) => T;

/**
 * Use the function for compile-time checking that all possible input
 * values are processed
 */
export function assertNever(obj: never, msg: string): never {
  console.error(msg, obj);
  throw new Error(msg);
}

/**
 * Throws an error with the provided error message if the condition is false.
 */
export function assert(
  condition: boolean,
  errorMessage: string
): asserts condition {
  if (!condition) throw new Error(errorMessage);
}

export function isDefined<T>(x: T): x is NonNullable<T> {
  return x !== undefined && x !== null;
}

/**
 * Throws an error if the property is not defined.
 */
export function assertIsDefined<T>(
  val: T,
  variableName = 'variable'
): asserts val is NonNullable<T> {
  if (val === undefined || val === null) {
    throw new Error(`${variableName} is not defined`);
  }
}

export function queryAll<E extends Element = Element>(
  el: Element,
  selector: string
): NodeListOf<E> {
  if (!el) throw new Error('element not defined');
  if (el.shadowRoot) {
    const r = el.shadowRoot.querySelectorAll<E>(selector);
    if (r.length > 0) return r;
  }
  return el.querySelectorAll<E>(selector);
}

export function query<E extends Element = Element>(
  el: Element | null | undefined,
  selector: string
): E | undefined {
  if (!el) return undefined;
  if (el.shadowRoot) {
    const r = el.shadowRoot.querySelector<E>(selector);
    if (r) return r;
  }
  return el.querySelector<E>(selector) ?? undefined;
}

export function queryAndAssert<E extends Element = Element>(
  el: Element | null | undefined,
  selector: string
): E {
  const found = query<E>(el, selector);
  if (!found) throw new Error(`selector '${selector}' did not match anything'`);
  return found;
}

/**
 * Returns true, if both sets contain the same members.
 */
export function areSetsEqual<T>(a: Set<T>, b: Set<T>): boolean {
  if (a.size !== b.size) {
    return false;
  }
  return containsAll(a, b);
}

/**
 * Returns true, if 'set' contains 'subset'.
 */
export function containsAll<T>(set: Set<T>, subSet: Set<T>): boolean {
  for (const value of subSet) {
    if (!set.has(value)) {
      return false;
    }
  }
  return true;
}

/**
 * Add value, if the set does not contain it. Otherwise remove it.
 */
export function toggleSetMembership<T>(set: Set<T>, value: T): void {
  if (set.has(value)) {
    set.delete(value);
  } else {
    set.add(value);
  }
}

export function unique<T>(item: T, index: number, array: T[]) {
  return array.indexOf(item) === index;
}

/**
 * Returns the elements that are present in every sub-array. If a compareBy
 * predicate is passed in, it will be used instead of strict equality. A new
 * array is always returned even if there is already just a single array.
 */
export function intersection<T>(
  arrays: T[][],
  compareBy: (t: T, u: T) => boolean = (t, u) => t === u
): T[] {
  // Array.prototype.reduce needs either an initialValue or a non-empty array.
  // Since there is no good initialValue for intersecting (∅ ∩ X = ∅), the
  // empty array must be checked separately.
  if (arrays.length === 0) {
    return [];
  }
  if (arrays.length === 1) {
    return [...arrays[0]];
  }
  return arrays.reduce((result, array) =>
    result.filter(t => array.find(u => compareBy(t, u)))
  );
}

/**
 * Returns the elements that are present in A but not present in B.
 */
export function difference<T>(
  a: T[],
  b: T[],
  compareBy: (t: T, u: T) => boolean = (t, u) => t === u
): T[] {
  return a.filter(aVal => !b.some(bVal => compareBy(aVal, bVal)));
}

export async function copyToClipbard(text: string, copyTargetName?: string) {
  await navigator.clipboard.writeText(text);
  fireAlert(document, `${copyTargetName ?? text} was copied to clipboard`);
}
