/**
 * @module skottie-player-sk
 * @description <h2><code>skottie-player-sk</code></h2>
 *
 * <p>
 *   Displays a CanvasKit-based Skottie animation and provides various controls.
 * </p>
 *
 */
import { $$ } from '../../../infra-sk/modules/dom';
import '../../../elements-sk/modules/icons/pause-icon-sk';
import '../../../elements-sk/modules/icons/play-arrow-icon-sk';
import '../../../elements-sk/modules/icons/settings-icon-sk';
import '../../../elements-sk/modules/spinner-sk';
import { html, TemplateResult } from 'lit-html';
import { repeat } from 'lit-html/directives/repeat';
import {
  Canvas,
  CanvasKit,
  CanvasKitInit as CKInit,
  ColorProperty,
  ManagedSkottieAnimation,
  OpacityProperty,
  SoundMap,
  Surface,
} from 'canvaskit-wasm';
import { define } from '../../../elements-sk/modules/define';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { LottieAnimation } from '../types';

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

function hexColor(c: number) {
  // eslint-disable-next-line no-bitwise
  const rgb = c & 0x00ffffff;
  return `#${rgb.toString(16).padStart(6, '0')}`;
}

function skRectIsEmpty(rect: Float32Array | null) {
  if (!rect) {
    return true;
  }
  return rect[2] <= rect[0] || rect[3] <= rect[1];
}

type Property = ColorProperty | OpacityProperty;

class PropList<T extends Property> {
  private readonly defaultVal: T;

  index: number = 0;

  list: T[];

  constructor(list: T[], defaultVal: T) {
    this.list = list;
    this.defaultVal = defaultVal;
  }

  current = (): T =>
    this.index >= this.list.length ? this.defaultVal : this.list[this.index];

  empty = () => !this.list.length;
}

// TODO(kjlubick) replace after https://skia-review.googlesource.com/c/skia/+/437316 is deployed
interface AnimationSegment {
  name: string;
  t0: number;
  t1: number;
}

export interface SkottiePlayerConfig {
  assets?: Record<string, ArrayBuffer>;
  fps: number;
  height: number;
  lottie: LottieAnimation;
  soundMap?: SoundMap;
  width: number;
}

function segmentLabel(s: AnimationSegment) {
  return `${s.name} [${s.t0.toFixed(2)} .. ${s.t1.toFixed(2)}]`;
}

// 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 currentScript = document.currentScript! as HTMLScriptElement;
const scriptOrigin = new URL(currentScript.src).origin;

const canvasReady: Promise<CanvasKit> = CanvasKitInit({
  locateFile: (file: string) => `${scriptOrigin}/static/${file}`,
});

export class SkottiePlayerSk extends ElementSk {
  private static template = (ele: SkottiePlayerSk): TemplateResult => {
    if (ele.loading) {
      return ele.loadingTemplate();
    }
    return ele.runningTemplate();
  };

  private runningTemplate = () => html` <div class="container">
    <div class="wrapper">
      <canvas
        class="skottie-canvas"
        id="skottie"
        width=${this.width * window.devicePixelRatio}
        height=${this.height * window.devicePixelRatio}
        style="max-width: 100%;max-height:100%;aspect-ratio: ${this.width /
        this.height}; background-color: ${this.bgColor}"
      >
        Your browser does not support the canvas tag.
      </canvas>
      <div class="controls" ?hidden=${!this.showControls}>
        <play-arrow-icon-sk
          @click=${this.onPlay}
          ?hidden=${!this.paused}
        ></play-arrow-icon-sk>
        <pause-icon-sk
          @click=${this.onPause}
          ?hidden=${this.paused}
        ></pause-icon-sk>
        <input
          type="range"
          min="0"
          max="100"
          @input=${this.onScrub}
          @change=${this.onScrubEnd}
          class="skottie-player-scrubber"
        />
        <settings-icon-sk @click=${this.onSettings}></settings-icon-sk>
      </div>
    </div>
    ${this.settingsTemplate()}
  </div>`;

  private settingsTemplate = () => html`
<div class=skottie-player-settings-container ?hidden=${!this.showSettings}>
  <div class=skottie-player-settings-row>
    <div class=skottie-player-settings-label>Colors</div>
    <select id=color-prop-select class=skottie-player-property-select
            @input=${
              this.onPropertySelect
            } ?disabled=${this.colorProps.empty()}>
      ${repeat(
        this.colorProps.list,
        (c: ColorProperty) => c.key,
        (c: ColorProperty, index: number) => html`
          <option value=${index}>${c.key}</option>
        `
      )}
    <select>
    <input type=color class=skottie-player-picker id=color-picker
           value=${hexColor(this.colorProps.current().value)}
           @input=${this.onColorInput} ?disabled=${this.colorProps.empty()}>
    <hr class=skottie-player-settings-divider>
  </div>
  <div class=skottie-player-settings-row>
    <div class=skottie-player-settings-label>Opacity</div>
    <select id=opacity-prop-select class=skottie-player-property-select
            @input=${
              this.onPropertySelect
            } ?disabled=${this.opacityProps.empty()}>
      ${repeat(
        this.opacityProps.list,
        (o: OpacityProperty) => o.key,
        (o: OpacityProperty, index: number) => html`
          <option value=${index}>${o.key}</option>
        `
      )}
    <select>
    <input type=range min=0 max=100 class=skottie-player-picker id=opacity-picker
           value=${this.opacityProps.current().value}
           @input=${this.onOpacityInput} ?disabled=${this.opacityProps.empty()}>
    <hr class=skottie-player-settings-divider>
  </div>
  <div class=skottie-player-settings-row>
    <div class=skottie-player-settings-label>Segments</div>
    <select id=segment-prop-select class=skottie-player-property-select
            style='width: 100%' @input=${this.onPropertySelect}>
      ${repeat(
        this.animationSegments,
        (s: AnimationSegment) => s.name,
        (s: AnimationSegment, index: number) => html`
          <option value=${index}>${segmentLabel(s)}</option>
        `
      )}
    <select>
    <hr class=skottie-player-settings-divider>
  </div>
  <div class=skottie-player-settings-row>
    <input type=button value=Close @click=${this.onSettings}>
  </div>
</div>
`;

  private loadingTemplate = () => html` <div
    class="player-loading"
    title="Loading animation and engine."
    style="aspect-ratio: ${this.width / this.height};"
  >
    <div>Loading</div>
    <spinner-sk active></spinner-sk>
  </div>`;

  private animation: ManagedSkottieAnimation | null = null; // Skottie Animation instance

  private _animationName: string = '';

  private animationSegments: AnimationSegment[] = []; // Selectable animation segments

  private bgColor: string = '#fff';

  private colorProps: PropList<ColorProperty> = new PropList([], {
    key: '',
    value: 0,
  });

  private currentSegment: AnimationSegment = { name: '', t0: 0, t1: 1 };

  private height: number = 0;

  private kit: CanvasKit | null = null; // CanvasKit instance

  private loading: boolean = true;

  private nativeFPS: number = 0; // Animation fps.

  private opacityProps: PropList<OpacityProperty> = new PropList([], {
    key: '',
    value: 1,
  });

  private paused: boolean;

  private renderFPS: number = 0;

  private scrubPlaying: boolean = false; // Animation was playing when the user started scrubbing.

  private seekPoint: number = 0; // Normalized [0..1] animation progress.

  private showSettings: boolean;

  private showControls: boolean = false;

  private skcanvas: Canvas | null = null; // Cached SkCanvas (surface.getCanvas()).

  private surface: Surface | null = null;

  private timeOrigin: number = 0; // Animation start time (ms).

  private totalDuration: number = 0; // Animation duration (ms).

  private width: number = 0;

  constructor() {
    super(SkottiePlayerSk.template);

    this.paused = this.hasAttribute('paused');
    this.showSettings = new URL(document.location.href).searchParams.has(
      'settings'
    );
  }

  getBackgroundColor(): string {
    const params = new URL(document.location.href).searchParams;
    return params.has('bg') ? params.get('bg')! : '#fff';
  }

  connectedCallback(): void {
    super.connectedCallback();
    const params = new URL(document.location.href).searchParams;
    this.width = this.hasAttribute('width')
      ? +this.getAttribute('width')!
      : 256;
    this.height = this.hasAttribute('height')
      ? +this.getAttribute('height')!
      : 256;
    this.showControls = params.has('controls');
    this.bgColor = this.getBackgroundColor();
    this._render();
  }

  initialize(config: SkottiePlayerConfig): Promise<void> {
    this.width = config.width;
    this.height = config.height;
    this.renderFPS = config.fps;
    this._animationName = config.lottie.nm as string;
    const params = new URL(document.location.href).searchParams;
    this.bgColor = this.getBackgroundColor();

    this._render();
    return canvasReady.then((ck: CanvasKit) => {
      // Set a large-ish decode cache limit to accommodate potentially large images.
      const CACHE_SIZE = 512 * 1024 * 1024;
      ck.setDecodeCacheLimitBytes(CACHE_SIZE);

      this.kit = ck;
      this.initializeSkottie(config.lottie, config.assets, config.soundMap);
      this._render();
    });
  }

  duration(): number {
    return (
      this.totalDuration * (this.currentSegment.t1 - this.currentSegment.t0)
    );
  }

  fps(): number {
    return this.nativeFPS;
  }

  animationName(): string {
    return this._animationName;
  }

  canvas(): HTMLCanvasElement | null {
    return this.querySelector<HTMLCanvasElement>('.skottie-canvas');
  }

  seek(t: number, forceRender: boolean = false): void {
    this.timeOrigin = Date.now() - this.duration() * t;

    if (!this.isPlaying()) {
      // Force-draw a static frame when paused.
      this.updateSeekPoint();
      this.drawFrame(forceRender);
    }
  }

  isPlaying(): boolean {
    return !this.paused;
  }

  pause(): void {
    if (this.isPlaying()) {
      this.paused = true;
      // Save the exact/current seek point at pause time.
      this.updateSeekPoint();
    }
  }

  play(): void {
    if (!this.isPlaying()) {
      this.paused = false;
      // Shift timeOrigin to continue from where we paused.
      this.seek(this.seekPoint);
      this.drawFrame();
    }
  }

  initializeSkottie(
    lottieJSON: LottieAnimation,
    assets?: Record<string, ArrayBuffer>,
    soundMap?: SoundMap
  ): void {
    if (!this.kit) {
      console.error('Could not load CanvasKit');
      return;
    }
    this.loading = false;

    // Rebuild the surface only if needed.
    if (
      !this.surface ||
      this.surface.width() !== this.width ||
      this.surface.height() !== this.height
    ) {
      this._render();

      if (this.surface) {
        this.surface.delete();
      }
      const canvasEle = $$<HTMLCanvasElement>('#skottie', this)!;
      this.surface = this.kit.MakeCanvasSurface(canvasEle);
      if (!this.surface) {
        throw new Error('Could not make SkSurface.');
      }
      // We don't need to call .delete() on the canvas because
      // the parent surface will do that for us.
      this.skcanvas = this.surface.getCanvas();
    }

    if (this.animation) {
      this.animation.delete();
    }

    this.animation = this.kit.MakeManagedAnimation(
      JSON.stringify(lottieJSON),
      assets,
      '',
      soundMap
    );
    if (!this.animation) {
      throw new Error('Could not parse Lottie JSON.');
    }

    this.totalDuration = this.animation.duration() * 1000;
    this.nativeFPS = this.animation.fps();
    this.seek(0);

    this.colorProps.list = this.animation.getColorProps();
    this.opacityProps.list = this.animation.getOpacityProps();
    this.animationSegments = [{ name: 'Full timeline', t0: 0, t1: 1 }].concat(
      this.animation.getMarkers() as AnimationSegment[]
    );
    this.currentSegment = this.animationSegments[0];

    this._render(); // re-render for animation-dependent elements (properties, etc).

    this.drawFrame(true);
  }

  private updateSeekPoint(): void {
    // t is in animation segment domain.
    const t = ((Date.now() - this.timeOrigin) / this.duration()) % 1;

    // map to the global animation timeline
    this.seekPoint =
      this.currentSegment.t0 +
      t * (this.currentSegment.t1 - this.currentSegment.t0);
    if (this.showControls) {
      const scrubber = this.querySelector<HTMLInputElement>(
        '.skottie-player-scrubber'
      );
      if (scrubber) {
        scrubber.value = String(this.seekPoint * 100);
      }
    }
  }

  private drawFrame(forceRender: boolean = false): void {
    if (!this.animation || !this.skcanvas || !this.kit || !this.surface) {
      return;
    }

    // When paused, the progress is fully controlled externally.
    if (this.isPlaying()) {
      this.updateSeekPoint();
      window.requestAnimationFrame(() => {
        this.drawFrame();
      });
    }

    let frame = (this.seekPoint * this.totalDuration * this.nativeFPS) / 1000;
    if (this.renderFPS > 0) {
      // When a render FPS is specified, quantize to the desired rate.
      const fpsScale = this.renderFPS / this.nativeFPS;
      frame = Math.trunc(frame * fpsScale) / fpsScale;
    }

    const damage = this.animation.seekFrame(frame);
    // Only draw frames when the content changes.
    if (forceRender || !skRectIsEmpty(damage)) {
      const bounds = this.kit.LTRBRect(
        0,
        0,
        this.width * window.devicePixelRatio,
        this.height * window.devicePixelRatio
      );
      this.animation.render(this.skcanvas, bounds);
      this.surface.flush();
    }
  }

  private onPlay(): void {
    this.play();
    this._render();
  }

  private onPause(): void {
    this.pause();
    this._render();
  }

  // This fires every time the user moves the scrub slider.
  private onScrub(e: Event): void {
    const target = e.target as HTMLInputElement;
    this.seek(target.valueAsNumber / 100);

    // Pause the animation while dragging the slider.
    if (this.isPlaying()) {
      this.scrubPlaying = true;
      this.pause();
    }
  }

  // This fires when the user releases the scrub slider.
  private onScrubEnd(): void {
    if (this.scrubPlaying) {
      this.scrubPlaying = false;
      this.play();
    }
  }

  private onSettings(): void {
    this.showSettings = !this.showSettings;
    this._render();
  }

  private onPropertySelect(e: Event): void {
    const target = e.target as HTMLSelectElement;
    switch (target.id) {
      case 'color-prop-select':
        this.colorProps.index = target.selectedIndex;
        this.querySelector<HTMLInputElement>('#color-picker')!.value = hexColor(
          this.colorProps.current().value
        );
        break;
      case 'opacity-prop-select':
        this.opacityProps.index = target.selectedIndex;
        this.querySelector<HTMLInputElement>('#opacity-picker')!.value = String(
          this.opacityProps.current().value
        );
        break;
      case 'segment-prop-select':
        this.currentSegment = this.animationSegments[target.selectedIndex];
        this.seek(0);
        this._render();
        break;
      default:
        console.warn('unknown property select', target);
        break;
    }
  }

  private onColorInput(e: Event): void {
    const val = (e.target as HTMLInputElement).value;
    const prop = this.colorProps.current();
    // TODO(kjlubick) Why is there this combination of ColorAsInt and Color?
    const r = parseInt(val.substring(1, 3), 16);
    const g = parseInt(val.substring(3, 5), 16);
    const b = parseInt(val.substring(5, 7), 16);
    prop.value = this.kit!.ColorAsInt(r, g, b, 1.0); // Treat colors as fully opaque.

    this.animation!.setColor(prop.key, this.kit!.Color(r, g, b, 1.0));
    this._render();

    if (!this.isPlaying()) {
      this.drawFrame();
    }
  }

  private onOpacityInput(e: Event): void {
    const prop = this.opacityProps.current();
    prop.value = (e.target as HTMLInputElement).valueAsNumber;

    this.animation!.setOpacity(prop.key, prop.value);
    this._render();

    if (!this.isPlaying()) {
      this.drawFrame();
    }
  }
}

define('skottie-player-sk', SkottiePlayerSk);
