/**
 * @module skottie-gif-exporter
 * @description <h2><code>skottie-gif-exporter</code></h2>
 *
 * <p>
 *   A skottie gif exporter
 * </p>
 *
 * @evt start - This event is generated when the saving process starts.
 *
 */
import { define } from 'elements-sk/define';
import 'elements-sk/select-sk';
import { html, render } from 'lit-html';
import { bytes, diffDate } from 'common-sk/modules/human';
import GIF from './gif';

const QUALITY_SCRUBBER_RANGE = 50;

const WORKERS_COUNT = 4;

const ditherOptions = [
  'FloydSteinberg',
  'FalseFloydSteinberg',
  'Stucki',
  'Atkinson',
];

const exportStates = {
  IDLE: 'idle',
  GIF_PROCESSING: 'gif processing',
  IMAGE_PROCESSING: 'image processing',
  COMPLETE: 'complete',
};

const renderHeader = (ele) => {
  if (ele._state.state === exportStates.IDLE) {
    return html`
      <button class="editor-header-save-button" @click=${ele._save}>Save</button>
    `;
  }
  if (ele._state.state === exportStates.COMPLETE) {
    return html`
      <button class="editor-header-save-button" @click=${ele._cancel}>Back</button>
    `;
  }
  return html`
    <button class="editor-header-save-button" @click=${ele._cancel}>Cancel</button>
  `;
};

const renderOption = (ele, item, index) => html`
  <div
    role="option"
    ?selected=${ele._state.ditherValue === index}
  >
    ${item}
  </div>
`;

const renderRepeatsLabel = (val) => {
  switch (val) {
    case -1:
      return 'No repeats';
    case 0:
      return 'Infinite repeats';
    case 1:
      return `${val} Repeat`;
    default:
      return `${val} Repeats`;
  }
};

const renderDither = (ele) => {
  if (ele._state.dither) {
    return html`
      <select-sk
        role="listbox"
        @selection-changed=${ele._ditherOptionChange}
      >
        ${ditherOptions.map((item, index) => renderOption(ele, item, index))}
      </select-sk>
    `;
  }
  return null;
};

const renderIdle = (ele) => html`
  <div class=form>
    <div class=form-elem>
      <div>Sample (${ele._state.quality})</div>
      <input id=sampleScrub type=range min=1 max=${QUALITY_SCRUBBER_RANGE} step=1
          @input=${ele._onSampleScrub} @change=${ele._onSampleScrubEnd}>
    </div>
    <div class=form-elem>
      <label class=number>
        <input
          type=number
          id=repeats
          .value=${ele._state.repeat}
          min=-1
          @input=${ele._onRepeatChange}
          @change=${ele._onRepeatChange}
        /> Repeats (${renderRepeatsLabel(ele._state.repeat)})
      </label>
    </div>
    <div class=form-elem>
      <checkbox-sk label="Dither"
         ?checked=${ele._state.dither}
         @click=${ele._toggleDither}>
      </checkbox-sk>
      ${renderDither(ele)}
    </div>
  </div>
`;

const renderComplete = (ele) => html`
  <section class=complete>
    <div class=export-info>
      <div class=export-info-row>
        Render Complete
      </div>
      <div class=export-info-row>
        Export Duration: ${ele._state.exportDuration}
      </div>
      <div class=export-info-row>
        File size: ${bytes(ele._state.blob.size)}
      </div>
    </div>
    <a
      class=download
      href=${ele._blobURL}
      download=${ele._getDownloadFileName()}
    >
      Download
    </a>
  </section>
`;

const renderExporting = (text) => html`
  <section class=exporting>
    <div>
      ${text}
    </div>
  </section>
`;

const renderImage = (ele) => renderExporting(`Creating snapshots: ${ele._state.progress}%`);

const renderGif = (ele) => renderExporting(`Creating GIF: ${ele._state.progress}%`);

const mainRenders = {
  [exportStates.IDLE]: renderIdle,
  [exportStates.IMAGE_PROCESSING]: renderImage,
  [exportStates.GIF_PROCESSING]: renderGif,
  [exportStates.COMPLETE]: renderComplete,
};

const renderMain = (ele) => mainRenders[ele._state.state](ele);

const template = (ele) => html`
  <div>
    <header class="editor-header">
      <div class="editor-header-title">Gif Exporter</div>
      <div class="editor-header-separator"></div>
      ${renderHeader(ele)}
    </header>
    <section class=main>
      ${renderMain(ele)}
    </section>
  </div>
`;

class SkottieGifExporterSk extends HTMLElement {
  constructor() {
    super();
    this._state = {
      quality: 50,
      repeat: -1,
      dither: false,
      ditherValue: 0,
      state: exportStates.IDLE,
      progress: 0,
      blob: null,
      exportDuration: 0,
    };
  }

  delay(time) {
    return new Promise((resolve) => setTimeout(resolve, time));
  }

  _onSampleScrub(ev) {
    this._state.quality = ev.target.value;
    this._render();
  }

  _onSampleScrubEnd(ev) {
    this._state.quality = ev.target.value;
    this._render();
  }

  _onRepeatChange(ev) {
    this._state.repeat = parseInt(ev.target.value, 10);
    this._render();
  }

  _toggleDither(e) {
    e.preventDefault();
    this._state.dither = !this._state.dither;
    this._render();
  }

  _ditherOptionChange(e) {
    e.preventDefault();
    this._state.ditherValue = e.detail.selection;
    this._render();
  }

  _getDownloadFileName() {
    return this.player.animationName() || 'animation.gif';
  }

  /*
  *
  * This method takes care of traversing all frames from the passed animation
  * it adds all frames to the gif instance with a 1 ms delay between frames
  * to prevent blocking the main thread.
  */
  async _processFrames() {
    const fps = this.player.fps();
    const duration = this.player.duration();
    const canvasElement = this.player.canvas();
    let currentTime = 0;
    const increment = 1000 / fps;
    this._state.state = exportStates.IMAGE_PROCESSING;
    this._render();
    while (currentTime < duration) {
      if (this._state.state !== exportStates.IMAGE_PROCESSING) {
        return;
      }
      await this.delay(1); // eslint-disable-line no-await-in-loop
      this.player.seek(currentTime / duration, true);
      this._gif.addFrame(canvasElement, { delay: increment, copy: true });
      this._state.progress = Math.round((currentTime / duration) * 100);
      currentTime += increment;
      this._render();
    }
    this._state.state = exportStates.GIF_PROCESSING;
    // Note: this render method belongs to the gif.js library, not the html-lit
    this._gif.render();
  }

  _cancel() {
    if (this._state.state === exportStates.GIF_PROCESSING) {
      this._gif.abort();
    }
    this._state.state = exportStates.IDLE;
    this._render();
  }

  _createGifExporter() {
    this._gif = new GIF({
      workers: WORKERS_COUNT,
      quality: this._state.quality,
      repeat: this._state.repeat,
      dither: this._state.dither ? ditherOptions[this._state.ditherValue] : false,
      transparent: 0x00000000,
      workerScript: '/static/gif.worker.js',
    });
    this._gif.on('finished', (blob) => {
      this._state.state = exportStates.COMPLETE;
      this._state.blob = blob;
      this._state.exportDuration = diffDate(this._startTime);
      this._blobURL = URL.createObjectURL(blob);
      this._render();
    });
    this._gif.on('progress', (value) => {
      this._state.progress = Math.round(value * 100);
      this._render();
    });
  }

  _start() {
    this._state.progress = 0;
    this._startTime = Date.now();
    this.dispatchEvent(new CustomEvent('start', {
      detail: '',
    }));
  }

  async _save() {
    this._start();
    this._createGifExporter();
    this._processFrames();
  }

  connectedCallback() {
    this._player = this.player;
    this._render();
    this.addEventListener('input', this._inputEvent);
  }

  disconnectedCallback() {
    this.removeEventListener('input', this._inputEvent);
  }

  /** @prop player {skottie-player-sk} Skottie player instance. */
  get player() { return this._player; }

  set player(val) {
    this._player = val;
  }

  _render() {
    render(template(this), this, { eventContext: this });
  }
}

define('skottie-gif-exporter', SkottieGifExporterSk);
