// @flow
import styles from './ReadMore.less';

import React, { PureComponent } from 'react';
import classnames from 'classnames';

import themeVars from '../private/themeVars';
import Button from '../Button/Button';
import ChevronIcon from '../ChevronIcon/ChevronIcon';

const { rowHeight, standardTypeRowSpan, interactionTypeRowSpan } = themeVars;
const buttonHeight = rowHeight * interactionTypeRowSpan;

const getMaxHeight = (maxLines?: number, maxRows?: number) => {
  if (maxLines) {
    return maxLines * rowHeight * standardTypeRowSpan;
  }

  if (maxRows) {
    return maxRows * rowHeight;
  }

  return 0;
};

type Props = {|
  children: React$Element<*>,
  maxLines?: number,
  maxRows?: number,
  moreLabel: string,
  lessLabel: string,
  backgroundComponentName?: 'card' | 'body'
|};
type State = {|
  showMore: boolean,
  tooLong: boolean,
  mounted: boolean
|};
class ReadMore extends PureComponent<Props, State> {
  static defaultProps = {
    moreLabel: 'More',
    lessLabel: 'Less',
    backgroundComponentName: 'card'
  };

  constructor(props: Props) {
    super(props);

    this.contentRef = null;

    this.state = {
      showMore: false,
      tooLong: false,
      mounted: false
    };
  }

  componentDidMount() {
    this.update();
  }

  componentDidUpdate() {
    this.update();
  }

  contentRef: ?HTMLDivElement;

  update = () => {
    const { maxLines, maxRows } = this.props;

    if (this.contentRef) {
      const { scrollHeight } = this.contentRef;

      const tooLong =
        scrollHeight > getMaxHeight(maxLines, maxRows) + buttonHeight;

      this.setState({ tooLong, mounted: true }); // eslint-disable-line
    }
  };

  setTextRef = (element: ?HTMLDivElement) => {
    this.contentRef = element;
  };

  handleShowMore = () => {
    this.setState({
      showMore: !this.state.showMore
    });
  };

  render() {
    const {
      children,
      maxLines,
      maxRows,
      moreLabel,
      lessLabel,
      backgroundComponentName
    } = this.props;
    const { tooLong, showMore, mounted } = this.state;

    const truncate = mounted ? !showMore && tooLong : true;
    const showFade = truncate && mounted;
    const fadeColor = styles[backgroundComponentName];
    const showMoreLessButton = tooLong && mounted;

    const contentStyle = truncate ? {
      maxHeight: getMaxHeight(maxLines, maxRows),
      overflow: 'hidden'
    } : {};

    return (
      <div>
        <div className={styles.content} style={contentStyle}>
          <div ref={this.setTextRef}>{children}</div>
          {showFade ? (
            <div className={classnames(styles.fadeOut, fadeColor)} />
          ) : null}
        </div>
        {showMoreLessButton ? (
          <Button color="transparent" onClick={this.handleShowMore}>
            {showMore ? lessLabel : moreLabel}
            <ChevronIcon
              direction={showMore ? 'up' : 'down'}
              size="standard"
              className={styles.chevron}
            />
          </Button>
        ) : null}
      </div>
    );
  }
}

export default ReadMore;

@@ -785,16 +785,41 @@
 %7C 'body'
+,%0A  onShowMore?: Function
 %0A%7C%7D;%0Atyp
@@ -1793,24 +1793,64 @@
 e = () =%3E %7B%0A
+    const %7B onShowMore %7D = this.props;%0A%0A
     this.set
@@ -1855,18 +1855,27 @@
 etState(
-%7B
 %0A
+      %7B%0A  
       sh
@@ -1907,17 +1907,126 @@
 ore%0A    
-%7D
+  %7D,%0A      () =%3E %7B%0A        if (onShowMore) %7B%0A          onShowMore(this.state.showMore);%0A        %7D%0A      %7D%0A    
 );%0A  %7D;%0A

Add 'onShowMore' event handler prop (#527)