import { getLocationHref } from '../main';
import {
  createElementID,
  getExpressionsPlugin,
} from '../utils/common';
import {
  extendPrototype,
} from '../utils/functionExtensions';
import {
  createSizedArray,
} from '../utils/helpers/arrays';
import createNS from '../utils/helpers/svg_elements';
import BaseRenderer from './BaseRenderer';
import IImageElement from '../elements/ImageElement';
import SVGShapeElement from '../elements/svgElements/SVGShapeElement';
import SVGTextLottieElement from '../elements/svgElements/SVGTextElement'; // eslint-disable-line import/no-cycle
import ISolidElement from '../elements/SolidElement';
import NullElement from '../elements/NullElement';

function SVGRendererBase() {
}

extendPrototype([BaseRenderer], SVGRendererBase);

SVGRendererBase.prototype.createNull = function (data) {
  return new NullElement(data, this.globalData, this);
};

SVGRendererBase.prototype.createShape = function (data) {
  return new SVGShapeElement(data, this.globalData, this);
};

SVGRendererBase.prototype.createText = function (data) {
  return new SVGTextLottieElement(data, this.globalData, this);
};

SVGRendererBase.prototype.createImage = function (data) {
  return new IImageElement(data, this.globalData, this);
};

SVGRendererBase.prototype.createSolid = function (data) {
  return new ISolidElement(data, this.globalData, this);
};

SVGRendererBase.prototype.configAnimation = function (animData) {
  this.svgElement.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
  this.svgElement.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
  if (this.renderConfig.viewBoxSize) {
    this.svgElement.setAttribute('viewBox', this.renderConfig.viewBoxSize);
  } else {
    this.svgElement.setAttribute('viewBox', '0 0 ' + animData.w + ' ' + animData.h);
  }

  if (!this.renderConfig.viewBoxOnly) {
    this.svgElement.setAttribute('width', animData.w);
    this.svgElement.setAttribute('height', animData.h);
    this.svgElement.style.width = '100%';
    this.svgElement.style.height = '100%';
    this.svgElement.style.transform = 'translate3d(0,0,0)';
    this.svgElement.style.contentVisibility = this.renderConfig.contentVisibility;
  }
  if (this.renderConfig.width) {
    this.svgElement.setAttribute('width', this.renderConfig.width);
  }
  if (this.renderConfig.height) {
    this.svgElement.setAttribute('height', this.renderConfig.height);
  }
  if (this.renderConfig.className) {
    this.svgElement.setAttribute('class', this.renderConfig.className);
  }
  if (this.renderConfig.id) {
    this.svgElement.setAttribute('id', this.renderConfig.id);
  }
  if (this.renderConfig.focusable !== undefined) {
    this.svgElement.setAttribute('focusable', this.renderConfig.focusable);
  }
  this.svgElement.setAttribute('preserveAspectRatio', this.renderConfig.preserveAspectRatio);
  // this.layerElement.style.transform = 'translate3d(0,0,0)';
  // this.layerElement.style.transformOrigin = this.layerElement.style.mozTransformOrigin = this.layerElement.style.webkitTransformOrigin = this.layerElement.style['-webkit-transform'] = "0px 0px 0px";
  this.animationItem.wrapper.appendChild(this.svgElement);
  // Mask animation
  var defs = this.globalData.defs;

  this.setupGlobalData(animData, defs);
  this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
  this.data = animData;

  var maskElement = createNS('clipPath');
  var rect = createNS('rect');
  rect.setAttribute('width', animData.w);
  rect.setAttribute('height', animData.h);
  rect.setAttribute('x', 0);
  rect.setAttribute('y', 0);
  var maskId = createElementID();
  maskElement.setAttribute('id', maskId);
  maskElement.appendChild(rect);
  this.layerElement.setAttribute('clip-path', 'url(' + getLocationHref() + '#' + maskId + ')');

  defs.appendChild(maskElement);
  this.layers = animData.layers;
  this.elements = createSizedArray(animData.layers.length);
};

SVGRendererBase.prototype.destroy = function () {
  if (this.animationItem.wrapper) {
    this.animationItem.wrapper.innerText = '';
  }
  this.layerElement = null;
  this.globalData.defs = null;
  var i;
  var len = this.layers ? this.layers.length : 0;
  for (i = 0; i < len; i += 1) {
    if (this.elements[i] && this.elements[i].destroy) {
      this.elements[i].destroy();
    }
  }
  this.elements.length = 0;
  this.destroyed = true;
  this.animationItem = null;
};

SVGRendererBase.prototype.updateContainerSize = function () {
};

SVGRendererBase.prototype.findIndexByInd = function (ind) {
  var i = 0;
  var len = this.layers.length;
  for (i = 0; i < len; i += 1) {
    if (this.layers[i].ind === ind) {
      return i;
    }
  }
  return -1;
};

SVGRendererBase.prototype.buildItem = function (pos) {
  var elements = this.elements;
  if (elements[pos] || this.layers[pos].ty === 99) {
    return;
  }
  elements[pos] = true;
  var element = this.createItem(this.layers[pos]);

  elements[pos] = element;
  if (getExpressionsPlugin()) {
    if (this.layers[pos].ty === 0) {
      this.globalData.projectInterface.registerComposition(element);
    }
    element.initExpressions();
  }
  this.appendElementInPos(element, pos);
  if (this.layers[pos].tt) {
    var elementIndex = ('tp' in this.layers[pos])
      ? this.findIndexByInd(this.layers[pos].tp)
      : pos - 1;
    if (elementIndex === -1) {
      return;
    }
    if (!this.elements[elementIndex] || this.elements[elementIndex] === true) {
      this.buildItem(elementIndex);
      this.addPendingElement(element);
    } else {
      var matteElement = elements[elementIndex];
      var matteMask = matteElement.getMatte(this.layers[pos].tt);
      element.setMatte(matteMask);
    }
  }
};

SVGRendererBase.prototype.checkPendingElements = function () {
  while (this.pendingElements.length) {
    var element = this.pendingElements.pop();
    element.checkParenting();
    if (element.data.tt) {
      var i = 0;
      var len = this.elements.length;
      while (i < len) {
        if (this.elements[i] === element) {
          var elementIndex = 'tp' in element.data
            ? this.findIndexByInd(element.data.tp)
            : i - 1;
          var matteElement = this.elements[elementIndex];
          var matteMask = matteElement.getMatte(this.layers[i].tt);
          element.setMatte(matteMask);
          break;
        }
        i += 1;
      }
    }
  }
};

SVGRendererBase.prototype.renderFrame = function (num) {
  if (this.renderedFrame === num || this.destroyed) {
    return;
  }
  if (num === null) {
    num = this.renderedFrame;
  } else {
    this.renderedFrame = num;
  }
  // console.log('-------');
  // console.log('FRAME ',num);
  this.globalData.frameNum = num;
  this.globalData.frameId += 1;
  this.globalData.projectInterface.currentFrame = num;
  this.globalData._mdf = false;
  var i;
  var len = this.layers.length;
  if (!this.completeLayers) {
    this.checkLayers(num);
  }
  for (i = len - 1; i >= 0; i -= 1) {
    if (this.completeLayers || this.elements[i]) {
      this.elements[i].prepareFrame(num - this.layers[i].st);
    }
  }
  if (this.globalData._mdf) {
    for (i = 0; i < len; i += 1) {
      if (this.completeLayers || this.elements[i]) {
        this.elements[i].renderFrame();
      }
    }
  }
};

SVGRendererBase.prototype.appendElementInPos = function (element, pos) {
  var newElement = element.getBaseElement();
  if (!newElement) {
    return;
  }
  var i = 0;
  var nextElement;
  while (i < pos) {
    if (this.elements[i] && this.elements[i] !== true && this.elements[i].getBaseElement()) {
      nextElement = this.elements[i].getBaseElement();
    }
    i += 1;
  }
  if (nextElement) {
    this.layerElement.insertBefore(newElement, nextElement);
  } else {
    this.layerElement.appendChild(newElement);
  }
};

SVGRendererBase.prototype.hide = function () {
  this.layerElement.style.display = 'none';
};

SVGRendererBase.prototype.show = function () {
  this.layerElement.style.display = 'block';
};

export default SVGRendererBase;
