/** Ray-casting algorithm to test if a point is inside a polygon */
export function pointInPolygon(lat: number, lng: number, polygon: [number, number][]): boolean {
  let inside = false;
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    const [yi, xi] = polygon[i];
    const [yj, xj] = polygon[j];
    if ((yi > lat) !== (yj > lat) && lng < ((xj - xi) * (lat - yi)) / (yj - yi) + xi) {
      inside = !inside;
    }
  }
  return inside;
}

/** Format a number in French locale */
export const fr = (n: number, decimals = 2) =>
  n.toLocaleString('fr-FR', { minimumFractionDigits: decimals, maximumFractionDigits: decimals });

export type CurrencyUnit = 'DU' | 'G1';

/** Format a G1 value in the given unit, with k/M suffix */
export function formatValue(g1Value: number, unit: CurrencyUnit, duDaily: number): string {
  const val = unit === 'DU' ? g1Value / duDaily : g1Value;
  const suffix = unit === 'DU' ? 'DU' : '\u011e1';
  if (val >= 1_000_000) return fr(val / 1_000_000) + ' M' + suffix;
  if (val >= 1_000) return fr(val / 1_000) + ' k' + suffix;
  return fr(val) + ' ' + suffix;
}

/** Binary-search count of udBlocks entries >= joinBlock (udBlocks is sorted ascending). */
export function countUdSince(udBlocks: number[], joinBlock: number): number {
  let lo = 0, hi = udBlocks.length;
  while (lo < hi) {
    const mid = (lo + hi) >> 1;
    if (udBlocks[mid] < joinBlock) lo = mid + 1;
    else hi = mid;
  }
  return udBlocks.length - lo;
}

/** Date to ISO-like string (yyyy-mm-dd) */
export const dateToString = (date: Date) =>
  date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2);

/** Number of days between a date and today */
export const getDays = (date: string | undefined) => {
  if (!date) return 0;
  const d = new Date(date);
  const today = new Date();
  return Math.floor(Math.abs(d.getTime() - today.getTime()) / (1000 * 3600 * 24));
};

/** Seniority ratio between two dates (days from today) */
export const getRatio = (date1: string | undefined, date2: string | undefined) => {
  return getDays(date1) / Math.max(getDays(date2), 1);
};

export const Block0Date = '2017-03-08';

export type Friend = {
  name: string;
  date: string;
};

export type TableFriend = Friend & {
  [key: string]: string | number;
  displayName: string;
  displayDate: string;
  du: number;
};
