/* eslint-disable no-use-before-define */
/**
 * @module modules/shaders-app-sk
 * @description <h2><code>shaders-app-sk</code></h2>
 *
 */
import CodeMirror from 'codemirror';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { html, TemplateResult } from 'lit/html.js';
import { $, $$ } from '../../../infra-sk/modules/dom';
import 'codemirror/mode/clike/clike'; // Syntax highlighting for c-like languages.
import { define } from '../../../elements-sk/modules/define';
import { errorMessage } from '../../../elements-sk/modules/errorMessage';
import { stateReflector } from '../../../infra-sk/modules/stateReflector';
import { HintableObject } from '../../../infra-sk/modules/hintable';
import type { Canvas, CanvasKit, Paint, Surface } from '../../wasm_libs/types/canvaskit'; // gazelle:ignore
import { isDarkMode } from '../../../infra-sk/modules/theme-chooser-sk/theme-chooser-sk';

import '../../../elements-sk/modules/error-toast-sk';
import '../../../elements-sk/modules/icons/edit-icon-sk';
import '../../../elements-sk/modules/icons/add-icon-sk';
import '../../../elements-sk/modules/icons/delete-icon-sk';
import '../../../infra-sk/modules/theme-chooser-sk';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import '../../../infra-sk/modules/app-sk';
import '../../../infra-sk/modules/uniform-fps-sk';
import '../../../infra-sk/modules/uniform-time-sk';
import '../../../infra-sk/modules/uniform-generic-sk';
import '../../../infra-sk/modules/uniform-dimensions-sk';
import '../../../infra-sk/modules/uniform-slider-sk';
import '../../../infra-sk/modules/uniform-mouse-sk';
import '../../../infra-sk/modules/uniform-color-sk';
import '../../../infra-sk/modules/uniform-imageresolution-sk';
import { UniformControl } from '../../../infra-sk/modules/uniform/uniform';
import { DimensionsChangedEventDetail } from '../../../infra-sk/modules/uniform-dimensions-sk/uniform-dimensions-sk';
import {
  defaultScrapBody,
  defaultShader,
  numPredefinedUniformLines,
  predefinedUniforms,
  ShaderNode,
} from '../shadernode';
import { EditChildShaderSk } from '../edit-child-shader-sk/edit-child-shader-sk';
import '../edit-child-shader-sk';
import '../window/window';
import type CKInit from '../../wasm_libs/types/canvaskit'; // gazelle:ignore

// It is assumed that canvaskit.js has been loaded and this symbol is available globally.
declare const CanvasKitInit: typeof CKInit;

// It is assumed that this symbol is being provided by a version.js file loaded in before this
// file.
declare const SKIA_VERSION: string;

// This element might be loaded from a different site, and that means we need
// to be careful about how we construct the URL back to the canvas.wasm file.
// Start by recording the script origin.
const scriptOrigin = new URL((document!.currentScript as HTMLScriptElement).src).origin;
const kitReady = CanvasKitInit({
  locateFile: (file: string) => `${scriptOrigin}/dist/${file}`,
});

const DEFAULT_SIZE = 512;

type stateChangedCallback = () => void;

// This works around a TS lint rule included in Bazel rules which requires promises be awaited
// on. We do not necessarily want to await on errorMessage, especially when we tell the error
// message to be up indefinitely.
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
function doNotWait(_: Promise<unknown>) {}

// State represents data reflected to/from the URL.
interface State {
  id: string;
}

const defaultState: State = {
  id: '@default',
};

// A convenience type that represents HTML Elements which are also UniformControls.
interface UniformControlElement extends Element, UniformControl {}

// Define a new mode and mime-type for SkSL shaders. We follow the shader naming
// covention found in CodeMirror.
CodeMirror.defineMIME('x-shader/x-sksl', { name: 'clike' });

/** requestAnimationFrame id if requestAnimationFrame is not running. */
const RAF_NOT_RUNNING = -1;

/**
 * Each shader example consists of a hash linking it to its corresponding webpages which updates
 * the codemirror and canvas. The image source is the source of the thumbnail image (a jpeg) and
 * the alt is the alternative text
 */
interface shaderExample {
  hash: string;
  imageName: string;
}

/** An array of shader examples. Each image name must correspond to the thumbnail name */
const exampleShaders: Array<shaderExample> = [
  {
    hash: 'de2a4d7d893a7251eb33129ddf9d76ea517901cec960db116a1bbd7832757c1f',
    imageName: 'blue-neurons',
  },

  {
    hash: 'ed72577c437c036447372e4c873462fc1bbfc0cb5e9fb0630ab1c07368a0db48',
    imageName: 'kaleidoscope',
  },

  {
    hash: 'f9be5248170044ea1b69ee78456eec4be98d3e71a6c61fd0138f6018abda2ac3',
    imageName: 'blue-clouds',
  },

  {
    hash: '2bee4488820c3253cd8861e85ce3cab86f482cfddd79cfd240591bf64f7bcc38',
    imageName: 'fibonacci-sphere',
  },

  {
    hash: '7cd08fc6b1b23121529c62e31e00b4bd6b49deba9a3904fd01fda3dc5c590050',
    imageName: 'mandelbrot',
  },

  {
    hash: '23a360c975c3cb195c89ccdf65ec549e279ce8a959643b447e69cb70614a6eca',
    imageName: 'smoke',
  },

  {
    hash: '80c3854680c3e99d71fbe24d86185d5bb20cb047305242f9ecb5aff0f102cf73',
    imageName: 'snowfall',
  },

  {
    hash: 'e0ec9ef204763445036d8a157b1b5c8929829c3e1ee0a265ed984aeddc8929e2',
    imageName: 'starfield',
  },

  {
    hash: 'e3c8c172e50a69196b2f7712c307ae7099931c3addfc21075ef4ab6aeed11f71',
    imageName: 'switch-color',
  },
];

// Records a display name and a scrap ID for a single uniform example.
interface uniformExample {
  name: string;
  id: string;
}

/** An array of shader examples. Each image name must correspond to the
 *  thumbnail name. See create-named-scraps.sh for how to update the contents of
 *  these named scraps.
 */
const uniformExamples: Array<uniformExample> = [
  {
    name: 'iResolution',
    id: '@iResolution',
  },
  {
    name: 'iTime',
    id: '@iTime',
  },
  {
    name: 'iMouse',
    id: '@iMouse',
  },
  {
    name: 'iImage',
    id: '@iImage',
  },
  {
    name: 'Controls',
    id: '@inputs',
  },
];

/**
 * A collection of thumbnail snippets that redirect to different shader examples when clicked on.
 * Additional examples can be added in example shaders with corresponding webpage hash and name
 * which in turn links to its thumbnail.
 * @returns the gallery template result
 */
const exampleShadersGalleryTemplate = () => html`
  <div class="gallery">
    <ol class="slides">
      ${exampleShaders.map((i) => shaderEntry(i))}
      ${uniformExamples.map((i) => uniformExampleEntry(i))}
    </ol>
  </div>
`;

/** DOM IDs must not contain an '@', so replace them, and also prepend 'x' so
 *  that the id never starts with a number.
 */
const domIDFromHashOrName = (hashOrName: string): string => {
  hashOrName = hashOrName.replace('@', '_');

  return `x${hashOrName}`;
};

/**
 * Formats each shader entry attaching the link, image source, and alternative text
 * @param i the shader example
 * @returns formated shader exanple entry div
 */
const shaderEntry = (i: shaderExample) =>
  html` <li class="thumbnails" id="${domIDFromHashOrName(i.hash)}">
    <a href="/?id=${i.hash}">
      <img src=${cdnImage(i)} alt=${`Clickable thumbnail of ${i.imageName} shader example`} />
    </a>
  </li>`;

/**
 * Formats each uniform entry attaching the link with the display text.
 */
const uniformExampleEntry = (uni: uniformExample) =>
  html` <li class="thumbnails" id="${domIDFromHashOrName(uni.id)}">
    <a href="/?id=${uni.id}">${uni.name}</a>
  </li>`;

/**
 * Formats the shader example thumbnail url
 * @param i a shader example
 * @returns the corrrect url for a shader example
 */
const cdnImage = (i: shaderExample) =>
  `https://cdn.skia.org/example-shaders/${i.imageName}-thumbnail.jpeg`;

export class ShadersAppSk extends ElementSk {
  private width: number = DEFAULT_SIZE;

  private height: number = DEFAULT_SIZE;

  private traceCoordX: number = DEFAULT_SIZE / 2;

  private traceCoordY: number = DEFAULT_SIZE / 2;

  private traceCoordClickMs: number = 0;

  private codeMirror: CodeMirror.Editor | null = null;

  private canvasEle: HTMLCanvasElement | null = null;

  private kit: CanvasKit | null = null;

  private surface: Surface | null = null;

  private canvas: Canvas | null = null;

  private paint: Paint | null = null;

  private rootShaderNode: ShaderNode | null = null;

  private currentNode: ShaderNode | null = null;

  /**
   * Records the lines that have been marked as having errors. We keep these
   * around so we can clear the error annotations efficiently.
   */
  private compileErrorLines: CodeMirror.TextMarker[] = [];

  private state: State = defaultState;

  /** The requestAnimationFrame id if we are running, otherwise we are not running. */
  private rafID: number = RAF_NOT_RUNNING;

  /** stateReflector update function. */
  private stateChanged: stateChangedCallback | null = null;

  private uniformControlsNeedingRAF: UniformControl[] = [];

  /**
   * Calculated when we render, it count the number of controls that are for
   * predefined uniforms, as opposed to user uniform controls.
   */
  private numPredefinedUniformControls: number = 0;

  private editChildShaderControl: EditChildShaderSk | null = null;

  constructor() {
    super(ShadersAppSk.template);
  }

  private static deleteButton = (
    ele: ShadersAppSk,
    parentNode: ShaderNode | null,
    node: ShaderNode,
    index: number
  ): TemplateResult => {
    if (ele.rootShaderNode === node || parentNode === null) {
      return html``;
    }
    return html`
      <button
        class="deleteButton"
        title="Delete child shader."
        @click=${(e: Event) => ele.removeChildShader(e, parentNode, index)}>
        <delete-icon-sk></delete-icon-sk>
      </button>
    `;
  };

  private static editButton = (
    ele: ShadersAppSk,
    parentNode: ShaderNode | null,
    node: ShaderNode,
    index: number
  ): TemplateResult => {
    if (ele.rootShaderNode === node || parentNode === null) {
      return html``;
    }
    return html`
      <button
        class="editButton"
        title="Edit child shader uniform name."
        @click=${(e: Event) => ele.editChildShader(e, parentNode, index)}>
        <edit-icon-sk></edit-icon-sk>
      </button>
    `;
  };

  private static displayShaderTreeImpl = (
    ele: ShadersAppSk,
    parentNode: ShaderNode | null,
    node: ShaderNode,
    depth: number = 0,
    name: string = '/',
    childIndex: number = 0
  ): TemplateResult[] => {
    let ret: TemplateResult[] = [];
    // Prepend some fixed width spaces based on the depth so we get a nested
    // directory type of layout. See https://en.wikipedia.org/wiki/Figure_space.
    const prefix = new Array(depth).fill('&numsp;&numsp;').join('');
    ret.push(
      html` <p class="childShader" @click=${() => ele.childShaderClick(node)}>
        <span>
          ${unsafeHTML(prefix)}
          <span class="linkish">${name}</span>
          ${ele.rootShaderNode!.children.length > 0 && ele.currentNode === node ? '*' : ''}
        </span>
        <span>
          ${ShadersAppSk.deleteButton(ele, parentNode, node, childIndex)}
          ${ShadersAppSk.editButton(ele, parentNode, node, childIndex)}
          <button
            class="addButton"
            title="Append a new child shader."
            @click=${(e: Event) => ele.appendChildShader(e, node)}>
            <add-icon-sk></add-icon-sk>
          </button>
        </span>
      </p>`
    );
    node.children.forEach((childNode, index) => {
      ret = ret.concat(
        ShadersAppSk.displayShaderTreeImpl(
          ele,
          node,
          childNode,
          depth + 1,
          node.getChildShaderUniformName(index),
          index
        )
      );
    });
    return ret;
  };

  private static displayShaderTree = (ele: ShadersAppSk): TemplateResult[] => {
    if (!ele.rootShaderNode) {
      return [html``];
    }
    return ShadersAppSk.displayShaderTreeImpl(ele, null, ele.rootShaderNode);
  };

  // TODO (anjulij): add this back to example shaders
  private static uniformControls = (ele: ShadersAppSk): TemplateResult[] => {
    const ret: TemplateResult[] = [
      html`<uniform-fps-sk></uniform-fps-sk>`, // Always start with the fps control.
    ];
    ele.numPredefinedUniformControls = 1;
    const node = ele.currentNode;
    if (!node) {
      return ret;
    }
    for (let i = 0; i < node.getUniformCount(); i++) {
      const uniform = node.getUniform(i);
      if (!uniform.name.startsWith('i')) {
        continue;
      }
      switch (uniform.name) {
        case 'iTime':
          ele.numPredefinedUniformControls++;
          ret.push(html`<uniform-time-sk .uniform=${uniform}></uniform-time-sk>`);
          break;
        case 'iMouse':
          ele.numPredefinedUniformControls++;
          ret.push(
            html`<uniform-mouse-sk
              .uniform=${uniform}
              .elementToMonitor=${ele.canvasEle}></uniform-mouse-sk>`
          );
          break;
        case 'iResolution':
          ele.numPredefinedUniformControls++;
          ret.push(
            html` <uniform-dimensions-sk
              .uniform=${uniform}
              @dimensions-changed=${ele.dimensionsChanged}></uniform-dimensions-sk>`
          );
          break;
        case 'iImageResolution':
          // No-op. This is no longer handled via uniform control, the
          // dimensions are handed directly into the ShaderNode from the image
          // measurements.
          break;
        default:
          if (uniform.name.toLowerCase().indexOf('color') !== -1) {
            ret.push(html`<uniform-color-sk .uniform=${uniform}></uniform-color-sk>`);
          } else if (uniform.rows === 1 && uniform.columns === 1) {
            ret.push(html`<uniform-slider-sk .uniform=${uniform}></uniform-slider-sk>`);
          } else {
            ret.push(html`<uniform-generic-sk .uniform=${uniform}></uniform-generic-sk>`);
          }
          break;
      }
    }
    return ret;
  };

  private static template = (ele: ShadersAppSk) => html`
    <app-sk>
      <header>
        <a href="/"><h1>SkSL Shaders</h1></a>
        <span>
          <a id="githash" href="https://skia.googlesource.com/skia/+show/${SKIA_VERSION}">
            ${SKIA_VERSION.slice(0, 7)}
          </a>
          <theme-chooser-sk class="theme-chooser"></theme-chooser-sk>
        </span>
      </header>
      <main>
        <div>
          <div class="example-gallery-and-canvas-wrapper">
            <div>${exampleShadersGalleryTemplate()}</div>
            <canvas id="player" width=${ele.width} height=${ele.height}>
              Your browser does not support the canvas tag.
            </canvas>
          </div>
          <div>${ShadersAppSk.displayShaderTree(ele)}</div>
        </div>
        <div>
          <details id="shaderinputs">
            <summary>Shader Inputs</summary>
            <textarea
              rows=${numPredefinedUniformLines}
              cols="75"
              readonly
              id="predefinedShaderInputs">
${predefinedUniforms}</textarea
            >
            <div id="imageSources">
              <figure>
                ${ele.currentNode?.inputImageElement}
                <figcaption>iImage1</figcaption>
              </figure>
              <details id="image_edit">
                <summary><edit-icon-sk></edit-icon-sk></summary>
                <div id="image_edit_dialog">
                  <label for="image_url"> Change the URL used for the source image. </label>
                  <div>
                    <input
                      type="url"
                      id="image_url"
                      placeholder="URL of image to use."
                      .value="${ele.currentNode?.getSafeImageURL() || ''}" />
                    <button @click=${ele.imageURLChanged}>Use</button>
                  </div>
                  <label for="image_upload">
                    Or upload an image to <em>temporarily</em> try as a source for the shader.
                    Uploaded images are not saved.
                  </label>
                  <div>
                    <input
                      @change=${ele.imageUploaded}
                      type="file"
                      id="image_upload"
                      accept="image/*" />
                  </div>
                </div>
              </details>
            </div>
          </details>
          <textarea
            style="display: ${ele.currentNode?.children.length ? 'block' : 'none'}"
            rows=${ele.currentNode?.children.length || 0}
            cols="75">
${ele.currentNode?.getChildShaderUniforms() || ''}</textarea
          >
          <div id="codeEditor"></div>
          <div ?hidden=${!ele.currentNode?.compileErrorMessage} id="compileErrors">
            <h3>Errors</h3>
            <pre>${ele.currentNode?.compileErrorMessage}</pre>
          </div>
        </div>
        <div id="shaderControls">
          <div
            id="uniformControls"
            @input=${ele.uniformControlsChange}
            @change=${ele.uniformControlsChange}>
            ${ShadersAppSk.uniformControls(ele)}
          </div>
          <button
            ?hidden=${!ele.rootShaderNode?.needsCompile()}
            @click=${ele.runClick}
            class="action">
            Run
          </button>
          <button
            ?hidden=${!ele.rootShaderNode?.needsSave()}
            @click=${ele.saveClick}
            class="action">
            Save
          </button>
          <button
            ?hidden=${ele.currentNode?.compileErrorMessage || ele.rootShaderNode?.needsCompile()}
            @click=${ele.createDebugTrace}
            class="action">
            Debug
          </button>
          <button
            ?hidden=${ele.rootShaderNode?.needsSave()}
            @click=${ele.viewInFiddle}
            class="action">
            View in fiddle
          </button>
          <button
            ?hidden=${ele.rootShaderNode?.needsSave()}
            @click=${ele.viewInJsFiddle}
            class="action">
            View in jsfiddle
          </button>
        </div>
      </main>
      <footer>
        <edit-child-shader-sk></edit-child-shader-sk>
        <error-toast-sk></error-toast-sk>
      </footer>
    </app-sk>
  `;

  /** Returns the CodeMirror theme based on the state of the page's darkmode.
   *
   * For this to work the associated CSS themes must be loaded. See
   * shaders-app-sk.scss.
   */
  private static themeFromCurrentMode = () => (isDarkMode() ? 'ambiance' : 'base16-light');

  connectedCallback(): void {
    super.connectedCallback();
    this._render();
    this.canvasEle = $$<HTMLCanvasElement>('#player', this);
    this.codeMirror = CodeMirror($$<HTMLDivElement>('#codeEditor', this)!, {
      lineNumbers: true,
      mode: 'x-shader/x-sksl',
      theme: ShadersAppSk.themeFromCurrentMode(),
      viewportMargin: Infinity,
      scrollbarStyle: 'native',
    });
    this.codeMirror.on('change', () => this.codeChange());
    this.editChildShaderControl = $$('edit-child-shader-sk', this);

    // Listen for theme changes.
    document.addEventListener('theme-chooser-toggle', () => {
      this.codeMirror!.setOption('theme', ShadersAppSk.themeFromCurrentMode());
    });

    // Listen for clicks on the canvas, to update the debug trace coordinate.
    this.canvasEle!.addEventListener('click', (e: MouseEvent) => {
      this.traceCoordX = Math.floor(e.offsetX);
      this.traceCoordY = Math.floor(e.offsetY);
      this.traceCoordClickMs = Date.now();
    });

    // Continue the setup once CanvasKit WASM has loaded.
    kitReady.then(async (ck: CanvasKit) => {
      this.kit = ck;
      this.paint = new this.kit.Paint();
      try {
        this.stateChanged = stateReflector(
          /* getState */ () => this.state as unknown as HintableObject,
          /* setState */ async (newState: HintableObject) => {
            this.state = newState as unknown as State;
            this.rootShaderNode = new ShaderNode(this.kit!);
            this.currentNode = this.rootShaderNode;
            if (!this.state.id) {
              await this.rootShaderNode.setScrap(defaultScrapBody);
              this.run();
            } else {
              await this.loadShaderIfNecessary();
            }
          }
        );
      } catch (error) {
        doNotWait(errorMessage(error as Error, 0));
      }
    });
  }

  private dimensionsChanged(e: Event) {
    const newDims = (e as CustomEvent<DimensionsChangedEventDetail>).detail;
    this.width = newDims.width;
    this.height = newDims.height;
    this.traceCoordX = Math.floor(this.width / 2);
    this.traceCoordY = Math.floor(this.height / 2);
    this.run();
  }

  private monitorIfDevicePixelRatioChanges() {
    // Use matchMedia to detect if the screen resolution changes from the current value.
    // See https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes
    const mqString = `(resolution: ${window.devicePixelRatio}dppx)`;
    matchMedia(mqString).addEventListener('change', () => this.run());
  }

  private async loadShaderIfNecessary() {
    if (!this.state.id) {
      return;
    }
    try {
      await this.rootShaderNode!.loadScrap(this.state.id);
      this._render();
      this.setUniformValuesToControls();
      // If we loaded this shader from the gallery then make sure the thumbnail
      // is scrolled into view.
      const galleryEntry = this.querySelector(`#${domIDFromHashOrName(this.state.id)}`);
      if (galleryEntry) {
        galleryEntry.scrollIntoView();
      }
      this.run();
    } catch (error) {
      doNotWait(errorMessage(error as Error, 0));
      // Return to the default view.
      this.state = Object.assign({}, defaultState);
      this.stateChanged!();
    }
  }

  private run() {
    this.monitorIfDevicePixelRatioChanges();
    // Cancel any pending drawFrames.
    if (this.rafID !== RAF_NOT_RUNNING) {
      cancelAnimationFrame(this.rafID);
      this.rafID = RAF_NOT_RUNNING;
    }

    // TODO(jcgregorio) In the long run maybe store scrollInfo and cursorPos
    // temporarily for each child shader so we restore the right view as the
    // user moves between child shaders?

    // Save the scroll info and the cursor position before updating the code.
    const scrollInfo = this.codeMirror!.getScrollInfo();
    const cursorPos = this.codeMirror!.getCursor();

    // Set code.
    this.codeMirror!.setValue(this.currentNode?.shaderCode || defaultShader);

    // Restore scroll info and cursor position.
    this.codeMirror!.setCursor(cursorPos);

    // Oddly CodeMirror TS doesn't have a Type defined for this shape.
    const scrollPosition = {
      left: scrollInfo.left,
      top: scrollInfo.top,
      right: scrollInfo.left + scrollInfo.width,
      bottom: scrollInfo.top + scrollInfo.height,
    };
    this.codeMirror!.scrollIntoView(scrollPosition);

    // eslint-disable-next-line no-unused-expressions
    this.surface?.delete();
    this.surface = this.kit!.MakeCanvasSurface(this.canvasEle!);
    if (!this.surface) {
      doNotWait(errorMessage('Could not make Surface.', 0));
      return;
    }
    // We don't need to call .delete() on the canvas because
    // the parent surface will do that for us.
    this.canvas = this.surface.getCanvas();
    this.clearAllEditorErrorAnnotations();

    this.rootShaderNode!.compile();

    // Set CodeMirror errors if the run failed.
    this.currentNode!.compileErrorLineNumbers.forEach((lineNumber: number) => {
      this.setEditorErrorLineAnnotation(lineNumber);
    });

    // Render so the uniform controls get displayed.
    this._render();
    this.drawFrame();
  }

  private clearAllEditorErrorAnnotations(): void {
    // eslint-disable-next-line no-unused-expressions
    this.compileErrorLines?.forEach((textMarker) => {
      textMarker.clear();
    });
  }

  private setEditorErrorLineAnnotation(lineNumber: number): void {
    // Set the class of that line to 'cm-error'.
    this.compileErrorLines.push(
      this.codeMirror!.markText(
        { line: lineNumber - 1, ch: 0 },
        { line: lineNumber - 1, ch: 9999 }, // Some large number for the character offset.
        {
          className: 'cm-error', // See the ambiance.css file in CodeMirror for the class name.
        }
      )
    );
  }

  /** Query the uniforms from the controls defined by the user. These uniforms will be packed into
   *  the beginning of the uniform buffer and be the same for all shaders. By being the same, this
   *  will allow a parent shader to be in sync with its children shaders.
   */
  private getPredefinedUniformValuesFromControls(): number[] {
    if (!this.currentNode) {
      return [];
    }
    const uniforms: number[] = new Array(this.currentNode.numPredefinedUniformValues).fill(0);
    $<UniformControlElement>('#uniformControls > *')
      .slice(0, this.numPredefinedUniformControls) // stop after the predefined controls
      .forEach((control: UniformControl) => {
        control.applyUniformValues(uniforms);
      });
    return uniforms;
  }

  /** Query the uniforms from the controls defined by the user. These uniforms will be packed
   *  into memory after the predefined uniforms (e.g. time, resolution).
   */
  private getUserUniformValuesFromControls(): number[] {
    if (!this.currentNode) {
      return [];
    }
    // Make a full array because the application of uniform values are implemented to write to
    // specific indexes and we need those later indexes to exist.
    const uniforms: number[] = new Array(this.currentNode.getUniformFloatCount()).fill(0);
    $<UniformControlElement>('#uniformControls > *')
      .slice(this.numPredefinedUniformControls) // start after the predefined controls
      .forEach((control: UniformControl) => {
        control.applyUniformValues(uniforms);
      });
    // Slice off the uniform values belonging to indices for the predefined uniforms. These
    // should all be zero anyway.
    return uniforms.slice(this.currentNode.numPredefinedUniformValues);
  }

  /** Populate the control values from the uniforms. */
  private setUniformValuesToControls(): void {
    const predefinedUniformValues = new Array(this.currentNode!.numPredefinedUniformValues).fill(0);
    const uniforms = predefinedUniformValues.concat(this.currentNode!.currentUserUniformValues);
    $<UniformControlElement>('#uniformControls > *').forEach((control: UniformControl) => {
      control.restoreUniformValues(uniforms);
    });
    this.findAllUniformControlsThatNeedRAF();
  }

  private findAllUniformControlsThatNeedRAF(): void {
    this.uniformControlsNeedingRAF = [];
    $<UniformControlElement>('#uniformControls > *').forEach((control: UniformControl) => {
      if (control.needsRAF()) {
        this.uniformControlsNeedingRAF.push(control);
      }
    });
  }

  private uniformControlsChange(): void {
    this.currentNode!.currentUserUniformValues = this.getUserUniformValuesFromControls();
    this._render();
  }

  private drawFrame(): void {
    const shader = this.currentNode!.getShader(this.getPredefinedUniformValuesFromControls());
    if (!shader || !this.kit) {
      return;
    }

    // Allow uniform controls to update, such as uniform-timer-sk.
    this.uniformControlsNeedingRAF.forEach((element) => {
      element.onRAF();
    });

    // Draw the shader.
    this.canvas!.clear(this.kit.BLACK);
    this.paint!.setShader(shader);
    const rect = this.kit.XYWHRect(0, 0, this.width, this.height);
    this.canvas!.drawRect(rect, this.paint!);

    // If the user recently clicked on the canvas to set the trace coordinate, circle it.
    // The circle pulses three times; each pulse lasts 200ms.
    const blinkMs: number = Date.now() - this.traceCoordClickMs;
    if (blinkMs < 600) {
      const phase = (blinkMs % 200) / 200; // increases from 0 to 1 over each pulse
      const paint: Paint = new this.kit.Paint();
      paint.setAntiAlias(true);
      paint.setStyle(this.kit.PaintStyle.Stroke);
      paint.setStrokeWidth(2.0);
      const opacity: number = 1.0 - phase;
      paint.setColor(this.kit.Color4f(1, 0, 0, opacity));
      const size: number = 10 + phase * 5;
      const ovalFrame = this.kit.XYWHRect(
        this.traceCoordX - size,
        this.traceCoordY - size,
        2 * size,
        2 * size
      );
      this.canvas!.drawOval(ovalFrame, paint);
      paint.delete();
    }

    this.surface!.flush();
    shader.delete();

    this.rafID = requestAnimationFrame(() => {
      this.drawFrame();
    });
  }

  private createDebugTrace(): void {
    const shader = this.currentNode!.getShader(this.getPredefinedUniformValuesFromControls());
    if (!shader || !this.kit) {
      return;
    }

    // Debug traces require a software surface.
    const surface: Surface = this.kit.MakeSurface(this.width, this.height)!;
    if (surface) {
      const canvas: Canvas = surface.getCanvas();
      const paint: Paint = new this.kit.Paint();
      const traced = this.kit.RuntimeEffect.MakeTraced(shader, this.traceCoordX, this.traceCoordY);
      paint.setShader(traced.shader);
      // Clip to a tight rectangle around the trace coordinate to reduce draw time.
      const tightClip = this.kit.XYWHRect(this.traceCoordX - 2, this.traceCoordY - 2, 5, 5);
      canvas.clipRect(tightClip, this.kit.ClipOp.Intersect, /* doAntiAlias= */ false);
      const rect = this.kit.XYWHRect(0, 0, this.width, this.height);
      canvas.drawRect(rect, paint);
      const traceJSON: string = traced.debugTrace.writeTrace();

      traced.shader.delete();
      traced.debugTrace.delete();
      paint.delete();
      surface.delete();

      // Write our trace JSON to HTML local storage, where the debugger can see it.
      localStorage.setItem('sksl-debug-trace', traceJSON);

      // Open the debugger in a separate tab, pointing it at our local storage buffer.
      window.open('/debug?local-storage', 'sksl-debug-target');
    }
    shader.delete();
  }

  private async viewInFiddle() {
    const loadInFiddle = function (scrapID: string) {
      const url = `${window.shaders.fiddle_origin}/scrap/sksl/${scrapID}`;
      window.open(url);
    };

    if (this.state.id) {
      loadInFiddle(this.state.id);
    } else {
      await this.saveClick();
      loadInFiddle(this.state.id);
    }
  }

  private async viewInJsFiddle() {
    const loadInJSFiddle = function (scrapID: string) {
      const url = `${window.shaders.jsfiddle_origin}/scrap/sksl/${scrapID}`;
      window.open(url);
    };

    if (this.state.id) {
      loadInJSFiddle(this.state.id);
    } else {
      await this.saveClick();
      loadInJSFiddle(this.state.id);
    }
  }

  private async runClick() {
    this.run();
    await this.saveClick();
  }

  private async saveClick() {
    try {
      this.state.id = await this.rootShaderNode!.saveScrap();
      this.stateChanged!();
      this._render();
    } catch (error) {
      doNotWait(errorMessage(error as Error, 0));
    }
  }

  private imageUploaded(e: Event) {
    const input = e.target as HTMLInputElement;
    if (!input.files?.length) {
      return;
    }
    const file = input.files.item(0)!;
    this.setCurrentImageURL(URL.createObjectURL(file));
  }

  private imageURLChanged(): void {
    const input = $$<HTMLInputElement>('#image_url', this)!;
    if (!input.value) {
      return;
    }
    this.setCurrentImageURL(input.value);
  }

  private codeChange() {
    if (!this.currentNode) {
      return;
    }
    this.currentNode.shaderCode = this.codeMirror!.getValue();
    this._render();
  }

  private async appendChildShader(e: Event, node: ShaderNode) {
    e.stopPropagation();
    try {
      await node.appendNewChildShader();
      this._render();
      await this.runClick();
    } catch (error) {
      doNotWait(errorMessage(error as Error));
    }
  }

  private async removeChildShader(e: Event, parentNode: ShaderNode, index: number) {
    e.stopPropagation();
    // We could write a bunch of complicated logic to track which current shader
    // is selected and restore that correctly on delete, or we can just always
    // shove the focus back to rootShaderNode which will always work, so we do
    // the latter.
    this.childShaderClick(this.rootShaderNode!);

    parentNode.removeChildShader(index);
    this._render();
    await this.runClick();
  }

  private async editChildShader(e: Event, parentNode: ShaderNode, index: number) {
    e.stopPropagation();
    const editedChildShader = await this.editChildShaderControl!.show(
      parentNode.getChildShader(index)
    );
    if (!editedChildShader) {
      return;
    }
    await parentNode.setChildShaderUniformName(index, editedChildShader.UniformName);
    this._render();
    await this.runClick();
  }

  private childShaderClick(node: ShaderNode) {
    this.currentNode = node;
    this.codeMirror!.setValue(this.currentNode?.shaderCode || defaultShader);
    this._render();
    this.setUniformValuesToControls();
  }

  /**
   * Load example by changing state rather than actually following the links.
   */
  private async fastLoad(e: Event): Promise<void> {
    const ele = e.target as HTMLLinkElement;
    if (ele.tagName !== 'A') {
      return;
    }
    e.preventDefault();
    // When switching shaders clear the file upload.
    $$<HTMLInputElement>('#image_upload')!.value = '';
    const id = new URL(ele.href).searchParams.get('id') || '';
    this.state.id = id;
    this.stateChanged!();
    await this.loadShaderIfNecessary();
  }

  private setCurrentImageURL(url: string): void {
    const oldURL = this.currentNode!.getCurrentImageURL();

    // Release unused memory.
    if (oldURL.startsWith('blob:')) {
      URL.revokeObjectURL(oldURL);
    }

    this.currentNode!.setCurrentImageURL(url).then(() => this._render());
  }
}

define('shaders-app-sk', ShadersAppSk);
