import React from 'react';
import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types';
import { noop } from 'node-noop';

class Printer extends React.Component {
  removeWindow= (target) => {
    setTimeout(() => {
      target.parentNode.removeChild(target);
    }, 500);
  }

  triggerPrint = (target) => {
    const { onAfterPrint } = this.props;

    setTimeout(() => {
      target.contentWindow.focus();
      target.contentWindow.print();
      this.removeWindow(target);

      if (onAfterPrint) {
        onAfterPrint();
      }
    }, 500);
  }

  handlePrint = () => {
    const {
      content,
    } = this.props;

    const contentEl = content();

    // eslint-disable-next-line no-undef
    const printWindow = document.createElement('iframe');
    printWindow.style.position = 'absolute';
    printWindow.style.top = '-1000px';
    printWindow.style.left = '-1000px';

    const contentNodes = findDOMNode(contentEl);
    // eslint-disable-next-line no-undef
    const linkNodes = document.querySelectorAll('link[rel="stylesheet"]');

    this.linkTotal = linkNodes.length || 0;
    this.linkLoaded = 0;

    const markLoaded = () => {
      this.linkLoaded += 1;

      if (this.linkLoaded === this.linkTotal) {
        this.triggerPrint(printWindow);
      }
    };

    printWindow.onload = () => {
      const domDoc = printWindow.contentDocument || printWindow.contentWindow.document;

      domDoc.open();
      domDoc.write(contentNodes.outerHTML);
      domDoc.close();

      const defaultPageStyle = '@page { size: auto;  margin: 0mm; } @media print { body { -webkit-print-color-adjust: exact; } }';

      const styleEl = domDoc.createElement('style');
      styleEl.appendChild(domDoc.createTextNode(defaultPageStyle));
      domDoc.head.appendChild(styleEl);

      // Copy all styles to print

      // eslint-disable-next-line no-undef
      const headEls = document.querySelectorAll('style, link[rel="stylesheet"]');

      [...headEls].forEach((node, index) => {
        const newHeadEl = domDoc.createElement(node.tagName);
        let styleCSS = '';

        if (node.tagName === 'STYLE') {
          if (node.sheet) {
            for (let i = 0; i < node.sheet.cssRules.length; i += 1) {
              styleCSS += `${node.sheet.cssRules[i].cssText}\r\n`;
            }

            newHeadEl.setAttribute('id', `printer-${index}`);
            newHeadEl.appendChild(domDoc.createTextNode(styleCSS));
          }
        } else {
          const attributes = [...node.attributes];
          attributes.forEach((attr) => {
            newHeadEl.setAttribute(attr.nodeName, attr.nodeValue);
          });

          newHeadEl.onload = markLoaded.bind(null, 'link');
          newHeadEl.onerror = markLoaded.bind(null, 'link');
        }

        domDoc.head.appendChild(newHeadEl);
      });
    };
    // eslint-disable-next-line no-undef
    document.body.appendChild(printWindow);
  }

  render() {
    const { trigger } = this.props;
    return React.cloneElement(trigger(), {
      ref: (el) => { this.triggerRef = el; },
      onClick: this.handlePrint
    });
  }
}

Printer.propTypes = {
  trigger: PropTypes.func.isRequired,
  content: PropTypes.func.isRequired,
  onAfterPrint: PropTypes.func,
};

Printer.defaultProps = {
  onAfterPrint: noop
};

export default Printer;
