/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react';
import CheckboxTree from 'react-checkbox-tree';
import { Voyager } from 'graphql-voyager';
import 'graphql-voyager/dist/voyager.css';
import PropTypes from 'prop-types';
import 'react-checkbox-tree/lib/react-checkbox-tree.css';
import './Preview.css';
import Worker from 'worker-loader!./graphql.worker';

const worker = new Worker();

/**
 * @file Preview
 * Handles the graphql voyager preview window
 * @module Preview
 * @extends React.Component
 */
export default class Preview extends React.Component {
  constructor(props) {
    super(props);
    const { translationFile } = this.props;
    this.state = {
      nodes: this.initNodes(),
      checked: this.initChecked(),
      graphql: this.getGraphQL(translationFile),
    };
  }

  /**
   * Called after everytime preview window's checkbox tree gets updated
   * @method
   * @param {Object} nextProps - new props
   */
  componentDidUpdate(nextProps) {
    const { translationFile } = this.props;
    if (nextProps.translationFile !== translationFile) {
      const nodes = [];
      const checked = [];
      Object.keys(translationFile.endpoints).forEach((realEndpoint) => {
        Object.keys(translationFile.endpoints[realEndpoint]).forEach((endpoint) => {
          nodes.push({
            value: `${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`,
            label: endpoint,
          });
          checked.push(`${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`);
        });
      });
      this.setState({ nodes, checked }, () => this.getGraphQL(translationFile));
    }
  }

  /**
   * Initalize the checkbox tree nodes
   * @method
   * @returns array of nodes
   */
  initNodes = () => {
    const { translationFile } = this.props;
    const nodes = [];
    Object.keys(translationFile.endpoints).forEach((realEndpoint) => {
      Object.keys(translationFile.endpoints[realEndpoint]).forEach((endpoint) => {
        nodes.push({
          value: `${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`,
          label: endpoint,
        });
      });
    });
    return nodes;
  };

  /**
   * Initalize the checkbox tree nodes checked states
   * @method
   * @returns array of checked nodes
   */
  initChecked = () => {
    const { translationFile } = this.props;
    const checked = [];
    Object.keys(translationFile.endpoints).forEach((realEndpoint) => {
      Object.keys(translationFile.endpoints[realEndpoint]).forEach((endpoint) => {
        checked.push(`${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`);
      });
    });
    return checked;
  };

  /**
   * Handle new checked nodes
   * @method
   * @param {Array} newChecked - array of the newly checked nodes
   */
  onCheckHandler = (newChecked) => {
    const { swaggerFile, translationFile } = this.props;

    const newFile = { sourceVersion: swaggerFile.info.version, endpoints: {} };

    // update translation file contents
    newChecked.forEach((node) => {
      const endpointName = node.substring(0, node.indexOf('/'));
      const endpoint = node.substring(node.indexOf('/'));

      newFile.endpoints[endpoint] = newFile.endpoints[endpoint] || {};

      newFile.endpoints[endpoint][endpointName] = translationFile.endpoints[endpoint][endpointName];
    });

    this.setState(
      {
        checked: newChecked,
      },
      () => this.getGraphQL(newFile),
    );
  };

  /**
   * Generate the graphql schema
   * @method
   * @param {Object} translationFile - the translation file
   */
  getGraphQL = (translationFile) => {
    const { swaggerFile } = this.props;

    worker.postMessage({ swaggerFile, translationFile });

    worker.addEventListener('message', (event) => {
      console.log(event.data);
      this.setState({ graphql: event.data });
    });
  };

  render() {
    const { nodes, checked, graphql } = this.state;

    return (
      <>
        <h3 className="filter-endpoints-text">Filter Endpoints</h3>
        <CheckboxTree
          checked={checked}
          nodes={nodes}
          onCheck={(newChecked) => this.onCheckHandler(newChecked)}
        />

        { graphql
          && <Voyager introspection={graphql} workerURI={`${process.env.PUBLIC_URL}/voyager.worker.js`} /> }
      </>
    );
  }
}

Preview.defaultProps = {
  swaggerFile: PropTypes.objectOf(PropTypes.object),
  translationFile: PropTypes.objectOf(PropTypes.object),
};

Preview.propTypes = {
  translationFile: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
  swaggerFile: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
};
