/* PageForm: KYDT edits the site's words, images and links in PageForm (pageform.coreshifthq.com).
   Each one is read from window.PageForm, with the text the page had before as the fallback, and
   tagged so the editor can find it. pageform-build puts the published content in each page with
   /_pageform/runtime.js and saves each page as it's drawn, so the words are in the served HTML.

   Opened without that build (wrangler pages dev site), there is no window.PageForm, and every
   helper shows its fallback.

   Keys are <page>.<section>.<name>, e.g. home.hero.lead; words on every page start with site. */

const pfFallback = {
  value: (k, f = '') => f,
  rich: (k, f = '') => f.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`),
  image: (k, f) => f,
  link: (k, f) => f,
  nav: (m, f = []) => f,
  attrs: () => ({}),
  navAttrs: () => ({}),
  use: () => {},
  ready: Promise.resolve(),
  drawn: () => {},
};
const PF = window.PageForm || pfFallback;

/* The props to pass on to the element. Not `{ k, ...rest }`: Babel Standalone compiles each
   text/babel script on its own and gives each one a global `_excluded` list for rest props, so two
   files using them overwrite each other's (motion.jsx's Reveal has one). */
function pfRest(props, omit) {
  const rest = Object.assign({}, props);
  omit.forEach((name) => delete rest[name]);
  return rest;
}

/* Plain text. `children` is the fallback: the words as they were. */
function T(props) {
  const Tag = props.as || 'span';
  return <Tag {...pfRest(props, ['k', 'children', 'as'])} {...PF.attrs(props.k)}>{PF.value(props.k, props.children)}</Tag>;
}

/* Text with bold, italic and links (Markdown in PageForm), on one line or as paragraphs. Only once
   a value is saved: the fallback shows as plain text. */
function RT(props) {
  const Tag = props.as || 'span';
  return <Tag {...pfRest(props, ['k', 'children', 'as', 'block'])} {...PF.attrs(props.k, 'rich')}
    dangerouslySetInnerHTML={{ __html: PF.rich(props.k, props.children, { inline: !props.block }) }} />;
}

/* An image the client can swap, keeping the site's own size and styling. */
function Img(props) {
  const img = PF.image(props.k, { src: props.src, alt: props.alt });
  return <img {...pfRest(props, ['k', 'src', 'alt'])} {...PF.attrs(props.k, 'image')} src={img.src} alt={img.alt} />;
}

/* A link the client can point somewhere else and relabel: { href, label, newTab }. */
const pfLink = (k, fallback) => PF.link(k, { newTab: false, ...fallback });

/* A number with its suffix ("30+"), editable as text and counted up from 0 where motion is on. */
function pfCount(k, fallback) {
  const shown = PF.value(k, fallback);
  const m = /^\s*(\d[\d,]*(?:\.\d+)?)(.*)$/.exec(shown);
  return m ? { shown, n: parseFloat(m[1].replace(/,/g, '')), suffix: m[2], dec: (m[1].split('.')[1] || '').length } : { shown };
}

Object.assign(window, { PF, T, RT, Img, pfLink, pfCount });
