text: import React, { Component } from 'react';
  import injectSheet from 'react-jss';
  import styles from './HTMLPage.styles';
  import { baseURL } from '../../utils';
  import { initInteractionElementDrawing } from './interaction-element-drawing';
  import config from '../../config';
  
  export class HTMLPage extends Component {
    iframeDocument = '';
  
    componentDidMount() {
      this.iframeDocument = this.node.contentDocument;
  
      // Create and insert html5 doctype
      const doctype = this.iframeDocument.implementation.createDocumentType('html', '', '');
      this.iframeDocument.insertBefore(doctype, this.iframeDocument.querySelector('html'));
      this.injectIframeContent();
    }
  
    componentDidUpdate() {
      this.injectIframeContent();
    }
  
    handleInteractionElementClick = event => {
      event.preventDefault();
      event.stopPropagation();
      if (!this.props.onInteractionElementClick) return;
  
      const attribute = event.target.attributes['data-interaction-id'];
      if (!attribute) return;
      this.props.onInteractionElementClick(attribute.value);
    }
  
    handleAddAnnotation = event => {
      event.preventDefault();
      if (!this.props.onAnnotate || !this.props.isAnnotationModeActive) return;
  
      this.props.onAnnotate({x: event.pageX - 20, y: event.pageY - 20 });
    }
  
    handleAnnotationClicked = event => {
      event.stopPropagation();
      const attribute = event.target.attributes['data-annotation-id'];
      if (!attribute) return;
  
      const annotationId = Number(attribute.value);
      console.log('annotation clicked', { annotationId });
      this.props.onSelectAnnotation(annotationId);
    }
  
    unhighlightInteractionElements = () => {
      this.iframeDocument.body.
        querySelectorAll('.interaction-element-rect').
        forEach(item => item.classList.remove('interaction-element-rect-highlighted'));
    }
  
    highlightInteractionElements = () => {
      this.iframeDocument.body.
        querySelectorAll('.interaction-element-rect').
        forEach(item => item.classList.add('interaction-element-rect-highlighted'));
  
      const elementsAdded = [];
  
      if (this.props.fileType === 'html') {
        this.iframeDocument.body.
          querySelectorAll('[data-interaction-id]').
          forEach(item => {
            const interactionId = item.attributes['data-interaction-id'].value;
            if (!interactionId || !this.props.viewLinks) return;
            const interactionTarget = this.props.viewLinks.find(link => link.interactionId === interactionId);
            if (!interactionTarget) return;
  
            const clientBoundary = item.getBoundingClientRect();
            const highlighted = this.iframeDocument.createElement('div');
            highlighted.style.position = 'absolute';
            highlighted.style.top = clientBoundary.top;
            highlighted.style.left = clientBoundary.left;
            highlighted.style.width = clientBoundary.width;
            highlighted.style.height = clientBoundary.height;
            highlighted.classList.add('interaction-element-rect-highlighted');
            highlighted.style.zIndex = 1000000;
            elementsAdded.push(highlighted);
            this.iframeDocument.body.append(highlighted);
          })
      }
  
      window.setTimeout(() => {
        this.unhighlightInteractionElements();
        elementsAdded.forEach(element => element.remove());
      }, 500);
    }
  
    injectIframeContent() {
      // Apply attributes to HTML element
      const htmlElement = this.iframeDocument.querySelector('html');
      Object.keys(this.props.htmlElementAttributes).forEach(attrName => {
        if (this.props.htmlElementAttributes[attrName])
          htmlElement.setAttribute(
            attrName,
            this.props.htmlElementAttributes[attrName]
          );
      });
  
      const additionalCSS = `
        <style>
          body {
            counter-reset: interactionElementCounter;
            cursor: ${ this.props.allowInteractionElementCreation ? 'crosshair' : 'default' };
            background: rgba(255, 255, 255, 0);
            width: ${config.widthForViewportSize[this.props.viewportSize]}px;
          }
  
          body:empty {
            background: transparent;
          }
  
          .annotation {
            position: absolute;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            z-index: 999999;
            background: #EE9A02;
            color: #FFF;
            line-height: 40px;
            text-align: center;
            font-family: Verdana, Sans Serif;
          }
  
          #new-interaction-element-rect {
            border: 1px dashed #EE9A02;
            background-color: rgb(240, 188, 72, 0.4);
            position: absolute;
            visibility: hidden;
          }
  
          .interaction-element-rect {
            border: 1px dashed #EE9A02;
            background-color: rgb(240, 188, 72, 0.4);
            position: absolute;
            opacity: ${this.props.allowInteractionElementCreation ? '1' : '0'};
            cursor: ${ this.props.allowInteractionElementCreation ? 'default' : 'pointer' };
          }
  
          .interaction-element-rect-highlighted {
            border: 1px dashed #EE9A02;
            background-color: rgb(240, 188, 72, 0.4);
            position: absolute;
            opacity: 1;
          }
  
          .interaction-element-rect::before {
            counter-increment: interactionElementCounter;
            content: counter(interactionElementCounter);
            color: #FFF;
            width: 20px;
            height: 20px;
            background: #EE9A02;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: Arial;
            font-size: 10px;
            margin-top: -10px;
            margin-left: -10px;
            visibility: ${this.props.allowInteractionElementCreation ? 'visible' : 'hidden'}
          }
        </style>`;
  
      const annotationsMarkup = this.props.isAnnotationModeActive ?
        this.props.annotations.map(annotation => `
        <div class='annotation' style='top: ${annotation.y}px; left: ${annotation.x}px; cursor: pointer;' data-annotation-id='${annotation.id}'>
          ${ annotation.index }
        </div>
      `).join('') : '';
  
      htmlElement.style = 'visibility: hidden';
  
      const newInteractionElementMarkup = this.props.allowInteractionElementCreation ?
        `<div id='new-interaction-element-rect'></div>` :
        '';
  
      const existingInteractionElementsMarkup = this.props.imageInteractionElements ?
        this.props.imageInteractionElements.map(item => `
          <div
            class='interaction-element-rect'
            data-interaction-id='${item.id}'
            style='left: ${item.x + this.props.horizontalOffset}px; top: ${item.y}px; width: ${item.width}px; height: ${item.height}px'
          >
          </div>
        `).join('') : '';
  
      // Fill head element
      this.iframeDocument.head.innerHTML = `${this.props.head} ${additionalCSS}`;
  
  
      // Fill body element
      const bodyHtml = `
        ${this.props.body}
        ${annotationsMarkup}
        ${newInteractionElementMarkup}
        ${existingInteractionElementsMarkup}`.trim();
      this.iframeDocument.body.innerHTML = bodyHtml;
  
      // Insert JavaScript and CSS assets to the view
      this.props.assets.forEach(asset => {
        switch (asset.type) {
          case 'js':
            this.iframeDocument.body.append(
              this.getScriptElement(this.iframeDocument, asset)
            );
            break;
          case 'css':
            this.iframeDocument.head.append(
              this.getLinkElement(this.iframeDocument, asset)
            );
            break;
          case 'img':
            this.iframeDocument.body.
              querySelectorAll(`img[data-image-id="${asset.imageId}"]`).
              forEach(img => {
                img.setAttribute('src', `${baseURL}/library/${asset.location}`);
              });
            break;
          default:
        }
      });
  
      this.iframeDocument.body.
        querySelectorAll('[data-interaction-id]').
        forEach(link => link.addEventListener('click', this.handleInteractionElementClick));
  
      if (this.props.isAnnotationModeActive) {
        this.iframeDocument.body.addEventListener('click', this.handleAddAnnotation);
  
        this.iframeDocument.body.
          querySelectorAll('.annotation').
          forEach(annotation => annotation.addEventListener('click', this.handleAnnotationClicked));
      }
  
      if (!this.props.isAnnotationModeActive) {
        this.iframeDocument.body.addEventListener('click', this.highlightInteractionElements);
      }
  
      if (this.props.allowInteractionElementCreation && this.props.onCreateInteractionElement) {
        initInteractionElementDrawing(
          this.iframeDocument.body,
          this.iframeDocument.body.querySelector('#new-interaction-element-rect'),
          this.props.horizontalOffset,
          this.props.onCreateInteractionElement);
      }
  
      setTimeout(() => { htmlElement.style = ''; }, 100); // eslint-disable-line max-statements-per-line
    }
  
    getLinkElement(iframe, asset) {
      const styleElement =
        asset.contents === null
          ? iframe.createElement('link')
          : iframe.createElement('style');
  
      if (asset.location === null) {
        styleElement.append(iframe.createTextNode(asset.contents));
      } else {
        styleElement.rel = 'stylesheet';
        styleElement.href = `${baseURL}/library/${asset.location}`;
      }
  
      return styleElement;
    }
  
    getScriptElement(iframe, asset) {
      const scriptElement = iframe.createElement('script');
  
      if (asset.location === null) {
        scriptElement.append(iframe.createTextNode(asset.contents));
      } else {
        scriptElement.src = `${baseURL}/library/${asset.location}`;
        scriptElement.async = false;
      }
  
      return scriptElement;
    }
  
    render() {
      return (
        <div className={ `${this.props.classes.HTMLPage} preview-wrapper ${this.props.viewportSize}` }>
          <iframe
            className={`preview ${this.props.viewportSize}`}
            frameBorder="0"
            ref={node => { this.node = node }}
          />
        </div>
      );
    }
  }
  
  export default injectSheet(styles)(HTMLPage);
  