/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */

// We should get rid of sync use entirely but until then the
// methods are marked as such.
/* eslint-disable node/no-sync */

import fs from 'fs';
import path from 'path';
import type {Icon} from 'flipper-ui-core';

export type Icons = {
  [key: string]: Icon['size'][];
};

let _icons: Icons | undefined;

function getIconsSync(staticPath: string): Icons {
  return (
    _icons! ??
    (_icons = JSON.parse(
      fs.readFileSync(path.join(staticPath, 'icons.json'), {encoding: 'utf8'}),
    ))
  );
}

export function buildLocalIconPath(icon: Icon) {
  return path.join(
    'icons',
    `${icon.name}-${icon.variant}-${icon.size}@${icon.density}x.png`,
  );
}

export function getLocalIconUrl(
  icon: Icon,
  url: string,
  basePath: string,
  registerIcon: boolean,
): string {
  // resolve icon locally if possible
  const iconPath = path.join(basePath, buildLocalIconPath(icon));
  if (fs.existsSync(iconPath)) {
    return iconPath;
  }
  if (registerIcon) {
    tryRegisterIcon(icon, url, basePath);
  }

  return url; // fall back to http URL
}

function tryRegisterIcon(icon: Icon, url: string, staticPath: string) {
  const entryName = icon.name + (icon.variant === 'outline' ? '-outline' : '');
  const {size} = icon;
  const icons = getIconsSync(staticPath);
  if (!icons[entryName]?.includes(size)) {
    const existing = icons[entryName] || (icons[entryName] = []);
    if (!existing.includes(size)) {
      // Check if that icon actually exists!
      fetch(url)
        .then((res) => {
          if (res.status !== 200) {
            throw new Error(
              // eslint-disable-next-line prettier/prettier
              `Trying to use icon '${entryName}' with size ${size} and density ${icon.density}, however the icon doesn't seem to exists at ${url}: ${res.status}`,
            );
          }
          if (!existing.includes(size)) {
            // the icon exists
            existing.push(size);
            existing.sort();
            fs.writeFileSync(
              path.join(staticPath, 'icons.json'),
              JSON.stringify(icons, null, 2),
              'utf8',
            );
            console.warn(
              `Added uncached icon "${entryName}: [${size}]" to /static/icons.json.`,
            );
          } else {
          }
        })
        .catch((e) => console.error(e));
    }
  }
}
