import { readFile, writeFile } from "fs";

import { Article, CardItem, LeanArticle, LeanMCMCard, MCMCard } from "./types";

export async function asyncLoadJSON<T>(filename: string): Promise<T> {
  return new Promise((resolve, reject) => {
    readFile(filename, "utf8", (err, data) => {
      if (err) {
        return reject(err);
      }
      resolve(JSON.parse(data));
    });
  });
}

export async function asyncSaveJSON(
  filename: string,
  data: any
): Promise<void> {
  return new Promise((resolve, reject) => {
    writeFile(filename, JSON.stringify(data), {}, err => {
      if (err) {
        return reject(err);
      }
      resolve();
    });
  });
}

export function leanCard(card: MCMCard): LeanMCMCard {
  return {
    colorIdentity: card.colorIdentity,
    colors: card.colors,
    convertedManaCost: card.convertedManaCost,
    edhrecRank: card.edhrecRank,
    manaCost: card.manaCost,
    mcmId: card.mcmId,
    name: card.name,
    number: card.number,
    rarity: card.rarity,
    scryfallId: card.scryfallId,
    subtypes: card.subtypes,
    supertypes: card.supertypes,
    text: card.text,
    type: card.type,
    types: card.types,
    set: card.set,
    scryfallImageUrl: card.scryfallImageUrl,
    scryfallUrl: card.scryfallUrl
  };
}

export function leanArticle(article: Article): LeanArticle {
  return {
    idArticle: article.idArticle,
    language: article.language.languageName,
    comments: article.comments,
    price: article.price,
    count: article.count,
    condition: article.condition
  };
}

export function onlyUnique(value: CardItem, index: number, self: CardItem[]) {
  return self.findIndex(c => c.name == value.name) == index;
}

export function filterDict<K extends keyof any, T>(
  arr: T[],
  list: Record<K, (i: T) => boolean>
): Record<K, T[]> {
  let out: Record<K, T[]> = Object.create(null);
  for (const key in list) {
    out[key] = arr.filter(list[key]);
  }
  return out;
}

export function spanBy<K extends keyof any, T>(
  arr: T[],
  spanFn: (i: T) => K
): Record<K, T[]> {
  let out: Record<K, T[]> = Object.create(null);
  arr.forEach(item => {
    let key = spanFn(item);
    if (key in out) {
      out[key].push(item);
    } else {
      out[key] = [item];
    }
  });
  return out;
}

export function dictMap<K extends keyof any, A, B>(
  dict: Record<K, A>,
  mapFn: (i: A, k: K) => B
): Record<K, B> {
  let out: Record<K, B> = Object.create(null);
  for (let key in dict) {
    out[key] = mapFn(dict[key], key);
  }
  return out;
}
