/**
 * @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 'common-sk/modules/dom'
import 'elements-sk/icon/pause-icon-sk'
import 'elements-sk/icon/play-arrow-icon-sk'
import 'elements-sk/icon/settings-icon-sk'
import 'elements-sk/spinner-sk'
import { define } from 'elements-sk/define'
import { html, render } from 'lit-html'
import { repeat } from 'lit-html/directives/repeat';

const CanvasKitInit = require('../../build/canvaskit/canvaskit.js');

const loadingTemplate = (ele) => html`
<div class=player-loading title="Loading animation and engine."
     style='width: ${ele._config.width}px; height: ${ele._config.height}px;'>
  <div>Loading</div>
  <spinner-sk active></spinner-sk>
</div>`;

const settingsTemplate = (ele) => html`
<div class=skottie-player-settings-container ?hidden=${!ele._state.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=${ele._onPropertySelect} ?disabled=${ele._props.color.empty()}>
      ${repeat(ele._props.color.list, (c) => c.key, (c, index) => html`
        <option value=${index}>${c.key}</option>
      `)}
    <select>
    <input type=color class=skottie-player-picker id=color-picker
           value=${hexColor(ele._props.color.current().value)}
           @input=${ele._onColorInput} ?disabled=${ele._props.color.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=${ele._onPropertySelect} ?disabled=${ele._props.opacity.empty()}>
      ${repeat(ele._props.opacity.list, (o) => o.key, (o, index) => html`
        <option value=${index}>${o.key}</option>
      `)}
    <select>
    <input type=range min=0 max=100 class=skottie-player-picker id=opacity-picker
           value=${ele._props.opacity.current().value}
           @input=${ele._onOpacityInput} ?disabled=${ele._props.opacity.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=${ele._onPropertySelect}>
      ${repeat(ele._props.segments, (s) => s.name, (s, index) => 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=${ele._onSettings}>
  </div>
</div>
`;

function segmentLabel(s) {
  return s.name + ' [' + s.t0.toFixed(2) + ' .. ' + s.t1.toFixed(2) + ']';
}

function hexColor(c) {
  let rgb = c & 0x00ffffff;
  return '#' + rgb.toString(16).padStart(6, '0');
}

const runningTemplate = (ele) => html`
<div class=container>
  <div class=wrapper>
    <canvas class=skottie-canvas id=skottie
            width=${ele._config.width * window.devicePixelRatio}
            height=${ele._config.height * window.devicePixelRatio}
            style='width: ${ele._config.width}px; height: ${ele._config.height}px;'>
      Your browser does not support the canvas tag.
    </canvas>
    <div class=controls ?hidden=${!ele._config.controls}>
      <play-arrow-icon-sk @click=${ele._onPlay} ?hidden=${!ele._state.paused}></play-arrow-icon-sk>
      <pause-icon-sk @click=${ele._onPause} ?hidden=${ele._state.paused}></pause-icon-sk>
      <input type=range min=0 max=100 @input=${ele._onScrub} @change=${ele._onScrubEnd}
             class=skottie-player-scrubber>
      <settings-icon-sk @click=${ele._onSettings}></settings-icon-sk>
    </div>
  </div>
  ${settingsTemplate(ele)}
</div>`;

// 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.src).origin;

const canvasReady = CanvasKitInit({
  locateFile: (file) => {
    return `${scriptOrigin}/static/${file}`;
  },
});

define('skottie-player-sk', class extends HTMLElement {
  constructor() {
    super();

    this._engine = {
      kit:       null, // CanvasKit instance
      context:   null, // CK context.
      animation: null, // Skottie Animation instance
      surface:   null, // SkSurface
      canvas:    null, // Cached SkCanvas (surface.getCanvas()).
    };

    this._state = {
      loading:        true,
      paused:         this.hasAttribute('paused'),
      scrubPlaying:   false, // Animation was playing when the user started scrubbing.
      duration:       0,     // Animation duration (ms).
      nativeFps:      0,     // Animation fps.
      timeOrigin:     0,     // Animation start time (ms).
      seekPoint:      0,     // Normalized [0..1] animation progress.
      showSettings:   (new URL(document.location)).searchParams.has('settings'),
      currentSegment: { 'name': '', 't0': 0, 't1': 1},  // One of the _props.segments
    };

    function PropList(list, defaultVal) {
      this.list       = list;
      this.defaultVal = defaultVal;
      this.index      = 0;
      this.empty      = () => { return !this.list.length; }
      this.current    = () => {
        return this.index >= this.list.length
            ? this.defaultVal
            : this.list[this.index];
      }
    };

    this._props = {
      color:    new PropList([], 0.0), // Configurable color properties
      opacity:  new PropList([], 1.0), // Configurable opacity properties
      segments: [],                    // Selectable animation segments
    };
  }

  connectedCallback() {
    this._config = {
      width:    this.hasAttribute('width')  ? this.getAttribute('width')  : 256,
      height:   this.hasAttribute('height') ? this.getAttribute('height') : 256,
      controls: (new URL(document.location)).searchParams.has('controls'),
    };
    this._render();
  }

  initialize(config) {
    this._config.width  = config.width;
    this._config.height = config.height;
    this._config.fps    = config.fps;

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

      this._engine.kit = ck;
      this._initializeSkottie(config.lottie, config.assets);
      this._render();
    });
  }

  duration() {
    return this._state.duration * (this._state.currentSegment.t1 - this._state.currentSegment.t0);
  }

  seek(t) {
    this._state.timeOrigin = (Date.now() - this.duration() * t);

    if (!this.isPlaying()) {
      // Force-draw a static frame when paused.
      this._updateSeekPoint();
      this._drawFrame();
    }
  }

  isPlaying() {
    return !this._state.paused;
  }

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

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

  _initializeSkottie(lottieJSON, assets) {
    this._state.loading = false;

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

      this._render();

      this._engine.surface && this._engine.surface.delete();
      let canvasEle = $$('#skottie', this);
      this._engine.surface = this._engine.kit.MakeCanvasSurface(canvasEle);
      if (!this._engine.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._engine.canvas = this._engine.surface.getCanvas();

      this._engine.context = this._engine.kit.currentContext();
    }

    this._engine.animation && this._engine.animation.delete();

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

    this._state.duration  = this._engine.animation.duration() * 1000;
    this._state.nativeFps = this._engine.animation.fps();
    this.seek(0);

    this._props.color.list   = this._engine.animation.getColorProps();
    this._props.opacity.list = this._engine.animation.getOpacityProps();
    this._props.segments     = [ { 'name': 'Full timeline', 't0': 0, 't1': 1 } ]
                                   .concat(this._engine.animation.getMarkers());
    this._currentSegment     = this._props.segments[0];

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

    this._drawFrame(true);
  }

  _updateSeekPoint() {
    // t is in animation segment domain.
    let t = ((Date.now() - this._state.timeOrigin) / this.duration()) % 1;

    // map to the global animation timeline
    this._state.seekPoint = this._state.currentSegment.t0
                          + t * (this._state.currentSegment.t1 - this._state.currentSegment.t0);
    if (this._config.controls) {
      let scrubber = this.querySelector('.skottie-player-scrubber');
      if (scrubber) {
        scrubber.value = this._state.seekPoint * 100;
      }
    }
  }

  _drawFrame(firstFrame) {
    if (!this._engine.animation || !this._engine.canvas) {
      return;
    }

    // When paused, the progress is fully controlled externally.
    if (this.isPlaying()) {
      this._updateSeekPoint();
      window.requestAnimationFrame(this._drawFrame.bind(this));
    }

    let frame = this._state.seekPoint * this.duration() * this._state.nativeFps / 1000;
    if (this._config.fps) {
      // When a render FPS is specified, quantize to the desired rate.
      const fpsScale = this._config.fps / this._state.nativeFps;
      frame = Math.trunc(frame * fpsScale) / fpsScale;
    }

    this._engine.kit.setCurrentContext(this._engine.context);
    var damage = this._engine.animation.seekFrame(frame);
    // Only draw frames when the content changes.
    // TODO: SkRect::isEmpty()?
    if (firstFrame || (damage.fRight > damage.fLeft && damage.fBottom > damage.fTop)) {
      this._engine.animation.render(this._engine.canvas, {
                                    fLeft: 0,
                                    fTop:  0,
                                    fRight:  this._config.width  * window.devicePixelRatio,
                                    fBottom: this._config.height * window.devicePixelRatio });
      this._engine.surface.flush();
    }
  }

  _render() {
    render(this._state.loading
               ? loadingTemplate(this)
               : runningTemplate(this),
           this, {eventContext: this});
  }

  _onPlay() {
    this.play();
    this._render();
  }

  _onPause() {
    this.pause();
    this._render();
  }

  // This fires every time the user moves the scrub slider.
  _onScrub(e) {
    this.seek(e.currentTarget.value / 100);

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

  // This fires when the user releases the scrub slider.
  _onScrubEnd(e) {
    if (this._state.scrubPlaying) {
      this._state.scrubPlaying = false;
      this.play();
    }
  }

  _onSettings() {
    this._state.showSettings = !this._state.showSettings;
    this._render();
  }

  _onPropertySelect(e) {
    switch (e.target.id) {
    case 'color-prop-select':
      this._props.color.index = e.target.value;
      this.querySelector('#color-picker').value = hexColor(this._props.color.current().value);
      break;
    case 'opacity-prop-select':
      this._props.opacity.index = e.target.value;
      this.querySelector('#opacity-picker').value = this._props.opacity.current().value;
      break;
    case 'segment-prop-select':
      this._state.currentSegment = this._props.segments[e.target.value];
      this.seek(0);
      this._render();
      break;
    }
  }

  _onColorInput(e) {
    let val = e.target.value;
    let prop = this._props.color.current();
    prop.value = this._engine.kit.Color(parseInt(val.substring(1, 3), 16),
                                        parseInt(val.substring(3, 5), 16),
                                        parseInt(val.substring(5, 7), 16),
                                        1.0); // Treat colors as fully opaque.

    this._engine.animation.setColor(prop.key, prop.value);
    this._render();

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

  _onOpacityInput(e) {
    let prop = this._props.opacity.current();
    prop.value = Number(e.target.value);

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

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