/**
 * @module skottie-text-editor
 * @description <h2><code>skottie-text-editor</code></h2>
 *
 * <p>
 *   A skottie text editor
 * </p>
 *
 *
 * @evt apply - This event is generated when the user presses Apply.
 *         The updated json is available in the event detail.
 *
 * @attr animation the animation json.
 *         At the moment it only reads it at load time.
 *
 */
import { define } from 'elements-sk/define';
import { html, render } from 'lit-html';

const originTemplateElement = (item) => html`
  <li class="text-element-origin">
    <b>${item.precompName}</b> > Layer ${item.layer.ind}
  </li>
`;

const originTemplate = (group) => html`
  <div class="text-element-item">
    <div class="text-element-label">
       Origin${group.items.length > 1 ? 's' : ''}:
    </div>
      <ul>
        ${group.items.map(originTemplateElement)}
      </ul>
  </div>
`;

const textElement = (item, element) => html`
  <li class="text-element">
    <div class="text-element-wrapper">
      <div class="text-element-item">
        <div class="text-element-label">
          Layer name:
        </div>
        <div>
          ${item.name}
        </div>
      </div>
      <div class="text-element-item">
        <div class="text-element-label">
          Layer text:
        </div>
        <textarea class="text-element-input"
          @change=${(ev) => element._onChange(ev, item)}
          @input=${(ev) => element._onChange(ev, item)}
          .value=${item.text}
        ></textarea>
      </div>
      <div>${originTemplate(item)}</div>
    </div>
  </li>
`;

const template = (ele) => html`
  <div>
    <header class="editor-header">
      <div class="editor-header-title">Text Editor</div>
      <div class="editor-header-separator"></div>
      <button class="editor-header-save-button" @click=${ele._toggleTextsCollapse}>${ele._state.areTextsCollapsed ? 'Ungroup Texts' : 'Group Texts'}</button>
      <button class="editor-header-save-button" @click=${ele._save}>Save</button>
    </header>
    <section>
      <ul class="text-container">
         ${ele._state.texts.map((item) => textElement(item, ele))}
      </ul>
    <section>
  </div>
`;

const LAYER_TEXT_TYPE = 5;
const COMP_ROOT_NAME = 'Root';
const LINE_FEED = 10;
const FORM_FEED = 13;

class SkottieTextEditorSk extends HTMLElement {
  constructor() {
    super();
    this._state = {
      texts: [],
      areTextsCollapsed: true,
    };
    this._animation = null
    this._originalAnimation = null
  }

  findPrecompName(animation, precompId) {
    const animationLayers = animation.layers;
    let comp = animationLayers.find((layer) => layer.refId === precompId);
    if (comp) {
      return comp.nm;
    }
    const animationAssets = animation.assets;
    animationAssets.forEach((asset) => {
      if (asset.layers) {
        asset.layers.forEach((layer) => {
          if (layer.refId === precompId) {
            comp = layer;
          }
        });
      }
    });
    if (comp) {
      return comp.nm;
    }
    return 'not found';
  }

  _buildTexts(animation) {
    const textsData = animation.layers // we iterate all layer at the root layer
      .filter((layer) => layer.ty === LAYER_TEXT_TYPE) // we filter all layers of type text
      .map((layer) => ({ layer: layer, parentId: '', precompName: COMP_ROOT_NAME })) // we map them to some extra data
      .concat(
        animation.assets // we iterate over the assets of the animation looking for precomps
          .filter((asset) => asset.layers) // we filter assets that of type precomp (by querying if they have a layers property)
          .reduce((accumulator, precomp) => { // we flatten into a single array layers from multiple precomps
            accumulator = accumulator.concat(precomp.layers
              .filter((layer) => layer.ty === LAYER_TEXT_TYPE) // we filter all layers of type text
              .map((layer) => ({ // we map them to some extra data
                layer: layer,
                parentId: precomp.id,
                precompName: this.findPrecompName(animation, precomp.id),
              })));
            return accumulator;
          }, []),
      )
      .reduce((accumulator, item, index) => { // this creates a dictionary with all available texts
        const key = this._state.areTextsCollapsed
          ? item.layer.nm // if texts are collapsed the key will be the layer name (nm)
          : (index + 1); // if they are not collapse we use the index as key to be unique
        if (!accumulator[key]) {
          accumulator[key] = {
            id: item.layer.nm,
            name: item.layer.nm,
            items: [],
            // this property is the text string of a text layer.
            // It's read as: Text Element > Text document > First Keyframe > Start Value > Text
            text: item.layer.t.d.k[0].s.t,
            precompName: item.precompName,
          };
        }

        accumulator[key].items.push(item);
        return accumulator;
      }, {});
    const texts = Object.keys(textsData)
      .map((key) => textsData[key]); // we map the dictionary back to an array to get the final texts to render

    this._state.texts = texts;
  }

  _save() {
    this.dispatchEvent(new CustomEvent('apply', {
      detail: {
        texts: this._state.texts,
      },
    }));
  }

  _toggleTextsCollapse() {
    this._state.areTextsCollapsed = !this._state.areTextsCollapsed;
    this._buildTexts(this._animation);
    this._render();
  }

  _sanitizeText(text) {
    let sanitizedText = '';
    for (let i = 0; i < text.length; i += 1) {
      if (text.charCodeAt(i) === LINE_FEED) {
        sanitizedText += String.fromCharCode(FORM_FEED);
      } else {
        sanitizedText += text.charAt(i);
      }
    }
    return sanitizedText;
  }

  _onChange(event, elem) {
    const text = this._sanitizeText(event.target.value);
    elem.text = text;
    elem.items.forEach((item) => {
      // this property is the text string of a text layer.
      // It's read as: Text Element > Text document > First Keyframe > Start Value > Text
      item.layer.t.d.k[0].s.t = text;
    });
  }

  _updateAnimation(animation) {
    if (animation && this._originalAnimation !== animation) {
      const clonedAnimation = JSON.parse(JSON.stringify(animation));
      this._buildTexts(clonedAnimation);
      this._animation = clonedAnimation;
      this._originalAnimation = animation;
      this._render();
    }
  }

  /** @prop animation {Object} new animation to traverse. */
  set animation(val) {
    this._updateAnimation(val);
  }

  connectedCallback() {
    this._updateAnimation(this.animation);
    this.addEventListener('input', this._inputEvent);
  }

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

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

define('skottie-text-editor', SkottieTextEditorSk);
