import React from 'react';
import PropTypes from 'prop-types';
import { Grid, Spinner } from 'patternfly-react';
import isEqual from 'lodash/isEqual';
import './terminal.scss';
import { isTerminalScrolledDown } from './TerminalHelper';
import { isExitCodeLoading } from '../../ForemanInventoryHelpers';

class Terminal extends React.Component {
  constructor(props) {
    super(props);
    this.terminal = React.createRef();
    this.state = {
      didUserScroll: false,
    };
  }

  componentDidMount() {
    this.scrollBottom();
  }

  componentDidUpdate({ logs: prevLogs }) {
    const { logs: currentLogs, autoScroll } = this.props;
    const { didUserScroll } = this.state;
    if (autoScroll && !didUserScroll && !isEqual(prevLogs, currentLogs)) {
      this.scrollBottom();
    }
  }

  handleScroll = e => {
    const { scrollTop, scrollHeight, offsetHeight } = e.target;
    const didUserScroll = isTerminalScrolledDown(
      scrollHeight,
      scrollTop,
      offsetHeight,
      100
    );
    this.setState({
      didUserScroll,
    });
  };

  scrollBottom = () => {
    const element = this.terminal.current;
    if (!element) {
      return;
    }
    const setHeightToBottom = () => {
      element.scrollTop = element.scrollHeight;
    };
    /** happens on tab switching when the terminal wasn't visible yet
     * and there was nothing to scroll, 250ms is enough to wait for the terminal to appear.
     */
    if (element.scrollHeight === 0) {
      setTimeout(setHeightToBottom, 250);
    } else {
      setHeightToBottom();
    }
  };

  render() {
    const { logs, error, exitCode } = this.props;
    let modifiedLogs = null;
    if (error !== null) {
      modifiedLogs = <p className="terminal_error">{error}</p>;
    } else if (Array.isArray(logs)) {
      modifiedLogs = logs.map((log, index) => <p key={index}>{log}</p>);
    } else {
      modifiedLogs = <p>{logs}</p>;
    }
    const loading = isExitCodeLoading(exitCode);
    return (
      <Grid.Col sm={12}>
        <div
          className="terminal"
          ref={this.terminal}
          onScroll={this.handleScroll}
        >
          <Grid fluid>
            <Grid.Row>
              <Grid.Col sm={12}>
                {modifiedLogs}
                <Spinner loading={loading} inverse inline size="xs" />
              </Grid.Col>
            </Grid.Row>
          </Grid>
        </div>
      </Grid.Col>
    );
  }
}

Terminal.propTypes = {
  logs: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.string),
    PropTypes.string,
  ]),
  error: PropTypes.string,
  exitCode: PropTypes.string,
  autoScroll: PropTypes.bool,
};

Terminal.defaultProps = {
  logs: null,
  error: null,
  exitCode: '',
  autoScroll: true,
};

export default Terminal;