---
import Footer from '../components/Footer.astro';
import Header from '../components/Header.astro';
import { absoluteUrl, optimizeOgImage, site } from '../lib/site';
import defaultOg from '../assets/og-default.jpg';
import themeInit from '../scripts/theme-init.js?raw';
import '../styles/global.css';

interface ArticleMeta {
  publishedTime: string;
  modifiedTime?: string;
  tags?: readonly string[];
}

interface Props {
  title?: string;
  description?: string;
  canonicalPath?: string;
  ogImage?: string;
  ogImageAlt?: string;
  ogImageWidth?: number;
  ogImageHeight?: number;
  ogType?: 'website' | 'article' | 'profile';
  article?: ArticleMeta;
  jsonLd?: Record<string, unknown> | Array<Record<string, unknown>>;
  noindex?: boolean;
  preloadMono?: boolean;
}

const {
  title = site.title,
  description = site.description,
  canonicalPath = Astro.url.pathname,
  ogImage,
  ogImageAlt = "Andras Schmelczer's personal site",
  ogImageWidth,
  ogImageHeight,
  ogType = 'website',
  article,
  jsonLd,
  noindex = false,
  preloadMono = false,
} = Astro.props;

const isRoot = title === site.title;
const pageTitle = isRoot ? site.title : `${title} · ${site.name}`;
const ogTitle = isRoot ? site.title : title;
const canonical = absoluteUrl(canonicalPath);

let resolvedOgImage = ogImage;
let resolvedOgWidth = ogImageWidth ?? 1200;
let resolvedOgHeight = ogImageHeight ?? 630;

if (!resolvedOgImage) {
  const generated = await optimizeOgImage(defaultOg);
  resolvedOgImage = generated.src;
  resolvedOgWidth = 1200;
  resolvedOgHeight = 630;
}

const ogImageUrl = resolvedOgImage.startsWith('http')
  ? resolvedOgImage
  : absoluteUrl(resolvedOgImage);
const jsonLdEntries = jsonLd ? (Array.isArray(jsonLd) ? jsonLd : [jsonLd]) : [];

// Head meta tags built as a single HTML string so prettier-plugin-astro
// doesn't shuffle them outside `<head>` when reformatting (it has trouble
// with mixed JSX-expression and raw element siblings inside <head>).
const attr = (value: string) =>
  value
    .replace(/&/g, '&amp;')
    .replace(/"/g, '&quot;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');

const articleMetaParts = article
  ? [
      `<meta property="article:published_time" content="${attr(article.publishedTime)}">`,
      article.modifiedTime
        ? `<meta property="article:modified_time" content="${attr(article.modifiedTime)}">`
        : '',
      `<meta property="article:author" content="${attr(absoluteUrl('/about/'))}">`,
      ...(article.tags ?? []).map(
        (tag) => `<meta property="article:tag" content="${attr(tag)}">`
      ),
    ]
  : [];

const monoPreloadHtml = preloadMono
  ? '<link rel="preload" href="/fonts/ibm-plex-mono-latin-400.woff2" as="font" type="font/woff2" crossorigin>'
  : '';

const headHtml = [
  monoPreloadHtml,
  `<link rel="alternate" type="application/rss+xml" title="${attr(`${site.name} RSS`)}" href="/rss.xml">`,
  `<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">`,
  `<link rel="icon" href="/favicon.ico" type="image/x-icon">`,
  `<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">`,
  `<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">`,
  `<link rel="manifest" href="/site.webmanifest">`,
  `<meta property="og:site_name" content="${attr(site.name)}">`,
  `<meta property="og:title" content="${attr(ogTitle)}">`,
  `<meta property="og:description" content="${attr(description)}">`,
  `<meta property="og:url" content="${attr(canonical)}">`,
  `<meta property="og:image" content="${attr(ogImageUrl)}">`,
  `<meta property="og:image:type" content="image/jpeg">`,
  `<meta property="og:image:alt" content="${attr(ogImageAlt)}">`,
  `<meta property="og:image:width" content="${resolvedOgWidth}">`,
  `<meta property="og:image:height" content="${resolvedOgHeight}">`,
  `<meta property="og:type" content="${attr(ogType)}">`,
  `<meta property="og:locale" content="en">`,
  ...articleMetaParts,
  `<meta name="twitter:card" content="summary_large_image">`,
  `<meta name="twitter:title" content="${attr(ogTitle)}">`,
  `<meta name="twitter:description" content="${attr(description)}">`,
  `<meta name="twitter:image" content="${attr(ogImageUrl)}">`,
  `<meta name="twitter:image:alt" content="${attr(ogImageAlt)}">`,
  ...jsonLdEntries.map(
    (entry) =>
      `<script type="application/ld+json">${JSON.stringify(entry).replace(/<\/script/gi, '<\\/script')}</script>`
  ),
].join('');
---

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1,viewport-fit=cover"
    />
    <title>{pageTitle}</title>
    <meta name="description" content={description} />
    <meta name="author" content={site.name} />
    <meta name="color-scheme" content="light dark" />
    <meta name="theme-color" content="#fbfaf7" media="(prefers-color-scheme: light)" />
    <meta name="theme-color" content="#151514" media="(prefers-color-scheme: dark)" />
    {noindex && <meta name="robots" content="noindex,follow" />}
    {!noindex && <link rel="canonical" href={canonical} />}
    <script is:inline data-theme-script set:html={themeInit} />
    <noscript
      ><style>
        .theme-switcher {
          display: none !important;
        }
      </style></noscript
    >
    <link
      rel="preload"
      href="/fonts/source-sans-3-latin-variable.woff2"
      as="font"
      type="font/woff2"
      crossorigin
    />
    <Fragment set:html={headHtml} />
  </head>
  <body>
    <Header />
    <main id="content" tabindex="-1">
      <slot />
    </main>
    <Footer />
  </body>
</html>
