/**
 * @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 { 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}`;
  },
}).ready();

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

    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._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).
      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._render();
  }

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

    this._render();
    return canvasReady.then((ck) => {
      this._engine.kit = ck;
      this._initializeSkottie(config.lottie);
      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) {
    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));
    if (!this._engine.surface) {
      throw new Error('Could not parse Lottie JSON.');
    }

    this._state.duration = this._engine.animation.duration() * 1000;
    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();
  }

  _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() {
    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));
    }

    this._engine.kit.setCurrentContext(this._engine.context);
    this._engine.animation.seek(this._state.seekPoint);
    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();
    }
  }
});
