import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { clone, dissoc, equals, mergeRight, path } from 'ramda';

import { withSite } from '../../addons/Site';
import '../../../public/lib/jwplayer/jwplayer';
import { printError } from '../../lib';

const propTypes = {
  /** Configuration for JWPlayer. */
  jwPlayerConfig: PropTypes.object.isRequired,

  /**
   * Called after the player is mounted.
   * @param {Object} jwPlayer - Player object.
   */
  onPlayerMounted: PropTypes.func,

  /**
   * StoryShare `Site`.
   * @private
   */
  site: PropTypes.object.isRequired,
};

/* eslint-disable max-len */

/**
 * JwPlayer - configures and renders video player using jwplayer library
 * The following props are required.
 * Link to Jwplayer setup options below
 * https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/
 * @returns {Object} component
 */
export class JwPlayer extends Component {
  /* eslint-enable max-len */

  playerDivRef = React.createRef();

  jwplayer = null;

  componentDidMount = () => {
    this.setupVideo();
  };

  /**
   * Enables video player to update if it hasn't been interacted with
   * @returns {Bool} - whether the component should continue lifecycle
   */
  shouldComponentUpdate = () => {
    let idle = true;

    if (this.jwplayer) {
      if (this.jwplayer.getState() !== 'idle') {
        idle = false;
      }
    }

    return idle;
  }

  /**
   * Enables video player to update if the config prop changes
   * @param {Object} prevProps - Previous props to compare to.
   * @returns {void}
   */
  componentDidUpdate = (prevProps) => {
    const { jwPlayerConfig } = this.props;
    if (!equals(jwPlayerConfig, prevProps.jwPlayerConfig)) {
      this.setupVideo();
    }
  };

  componentWillUnmount = () => {
    try {
      this.jwplayer.remove();
    } catch (err) {
      /* eslint-disable no-console */
      printError('There was an error unmounting the video player.');
    }
  };

  setupVideo = () => {
    const { jwPlayerConfig, onPlayerMounted, site } = this.props;

    if (this.jwplayer) {
      this.jwplayer.remove();
    }

    const defaultSetup = {
      base: `${__webpack_public_path__}lib/jwplayer`, // eslint-disable-line
      abouttext: site.getSchema().name,
      aboutlink: site.getSchema().url,
      width: '100%',
      aspectratio: '16:9',
    };

    // JWPlayer mutates jwPlayerConfig prop i.e the 'playlist' by
    // adding some new properties it needs to work. So here we clone it to
    // prevent false positives about prop changes
    let setup = mergeRight(defaultSetup, clone(jwPlayerConfig));

    if (setup.height) {
      setup = dissoc('aspectratio', setup);
    }

    window.jwplayer.key = path(['keys', 'jwplayer_8'], site.getSchema());
    this.jwplayer = window.jwplayer(this.playerDivRef.current);

    try {
      this.jwplayer.setup(setup);
    } catch (err) {
      /* eslint-disable no-console */
      printError(
        'There was an error with the setup configuration of the video player.'
      );
      return;
    }

    if (onPlayerMounted) {
      onPlayerMounted(this.jwplayer);
    }
  };

  render = () => <div ref={ this.playerDivRef } />
}

JwPlayer.propTypes = propTypes;

export default withSite(JwPlayer);
