import { isEqual } from 'lodash-es';
import PropTypes from 'prop-types';
import React from 'react';
import {
  Button,
  Glyphicon,
  Label,
  OverlayTrigger,
  Panel,
  Tooltip,
} from 'react-bootstrap';
import TimeAgo from 'react-timeago';
import {
  ANNOTATION,
  EVENT_CATEGORY_COMMENT,
  LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT,
  LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT,
  LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT,
  LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT,
} from '../../constants/eventTypes';
import TagsSelectorContainer from '../../containers/Logbook/Tags/TagsSelectorContainer';
import { getContent } from '../../helpers/eventHelpers';
import EditorWrapper from './Editor/EditorWrapper';
import EventFooter from './EventFooter';
import EventVersions from './EventVersions';

/**
 * React component which renders a Panel for creating of editing an event
 */
class NewOrEditEventPanel extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isSaveButtonEnabled: false, //whether the editor contains some text or not
      isEditorContentValid: false,
      optionPanelDecollaped: false,
      selectedTags: [], // tags which are currently selected
    };

    this.isSaveButtonEnabled = this.isSaveButtonEnabled.bind(this);
    this.onCancelButtonClicked = this.onCancelButtonClicked.bind(this);
    this.onEventContentChanged = this.onEventContentChanged.bind(this);
    this.onSaveButtonClicked = this.onSaveButtonClicked.bind(this);
    this.onTagSelectionChanged = this.onTagSelectionChanged.bind(this);
  }

  render() {
    const { event, user, investigationId } = this.props;

    return (
      <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
        <div style={{ flex: '0 0 33px' }}>
          <Panel bsStyle="primary" style={{ marginBottom: 0 }}>
            <Panel.Heading style={{ padding: '5px 15px' }}>
              <b>{this.props.event ? 'Edit' : 'New comment'}</b>
              <div className="pull-right">
                <AuthorAndTime event={event} />
              </div>
            </Panel.Heading>
          </Panel>
        </div>

        <div style={{ flex: '2 2 70%' }}>
          <EditorWrapper
            event={event}
            investigationId={investigationId}
            onContentChanged={this.onEventContentChanged}
            user={user}
          />
        </div>

        <div style={{ flex: '1 1 32px', padding: '5px 10px 0 10px' }}>
          <div style={{ display: 'flex' }}>
            <div style={{ flex: '0 0 70px' }}>
              <h5 style={{ marginTop: 5, marginBottom: 5 }}>
                <Label style={{ margin: '0 6px 0 0', paddingRight: 2 }}>
                  {' '}
                  Tags{' '}
                </Label>
                <OverlayTrigger
                  placement="top"
                  overlay={
                    <Tooltip id="tooltip">
                      {' '}
                      <p> Manage tags </p>{' '}
                    </Tooltip>
                  }
                >
                  <a
                    href={`/investigation/${this.props.investigationId}/events/tagManager`}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    {' '}
                    <Glyphicon glyph="cog" />{' '}
                  </a>
                </OverlayTrigger>
              </h5>
            </div>
            <div style={{ flex: '1 1 100px' }}>
              <TagsSelectorContainer
                investigationId={this.props.investigationId}
                onChange={this.onTagSelectionChanged}
                tags={this.props.event ? this.props.event.tag : []}
              />
            </div>
          </div>
        </div>

        <div style={{ flex: '0 0 37px' }}>
          <EventFooter
            isSaveButtonEnabled={true}
            onCancelButtonClicked={() => this.onCancelButtonClicked()}
            onSaveButtonClicked={() => this.onSaveButtonClicked()}
          />
        </div>
      </div>
    );
  }

  /**
   * Function triggered when the tag selection has changed
   * @param {array} selectedTags tags currently selected by the user on the widget
   */
  onTagSelectionChanged(selectedTags) {
    this.setState({ selectedTags });
  }

  /**
   * Function triggered when the event content has changed
   */
  onEventContentChanged() {
    let isEditorContentValid = false;

    if (this.props.event) {
      //editing an event
      const currentTextInEditionMode = localStorage.getItem(
        LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT +
          this.props.event._id
      );
      isEditorContentValid =
        currentTextInEditionMode !== '' &&
        currentTextInEditionMode !==
          getContent(this.props.event.content, 'plainText');
    } else {
      //creating an event
      const currentTextInCreationMode = localStorage.getItem(
        LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT
      );
      isEditorContentValid = currentTextInCreationMode !== '';
    }
    this.setState({ isEditorContentValid });
  }

  /** Enable or disable the save button (unsused)*/
  isSaveButtonEnabled() {
    if (this.props.event) {
      //editing an event
      return (
        this.state.isEditorContentValid ||
        !isEqual(
          this.props.event.tag.map((tag) => tag._id).sort(),
          this.state.selectedTags.map((tag) => tag._id).sort()
        )
      );
    }
    //creating an event
    return this.state.isEditorContentValid;
  }

  /**
   * Callback function triggered when the user clicks on the cancel button
   */
  onCancelButtonClicked() {
    if (this.props.event) {
      // edition of an event
      this.props.onCancelButtonClicked();
    } else {
      // creation of an event
      localStorage.removeItem('plainText');
      localStorage.removeItem('HTMLText');
      this.props.onCancelButtonClicked();
    }
  }

  /**
   * Callback function triggered when the user click the save button while an event is being created or updated.
   */
  onSaveButtonClicked() {
    const currentTagIds = this.state.selectedTags.map((tag) => tag._id);
    if (this.props.event) {
      // edition of an event
      const { event, user } = this.props;

      this.props.onSaveButtonClicked({
        _id: event._id,
        category: event.category,
        content: [
          {
            format: 'plainText',
            text: localStorage.getItem(
              LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT +
                event._id
            ),
          },
          {
            format: 'html',
            text: localStorage.getItem(
              LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT + event._id
            ),
          },
        ],
        creationDate: Date(),
        type: event.type,
        tag: currentTagIds,
        title: null,
        username: user.username,
        previousVersionEvent: event._id,
      });
    } else {
      // creation of an event
      this.props.onSaveButtonClicked({
        category: EVENT_CATEGORY_COMMENT,
        content: [
          {
            format: 'plainText',
            text: localStorage.getItem(
              LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT
            ),
          },
          {
            format: 'html',
            text: localStorage.getItem(
              LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT
            ),
          },
        ],
        creationDate: Date(),
        investigationId: this.props.investigationId,
        title: null,
        tag: currentTagIds,
        type: ANNOTATION,
        username: this.props.user.username,
      });
    }
  }
}

/** Render author and time */
const AuthorAndTime = (props) => {
  if (props.event) {
    return (
      <h5 style={{ marginTop: 0, marginBottom: 0 }}>
        <small style={{ color: 'white' }}>
          {' '}
          <em>
            @{props.event.username} -{' '}
            <TimeAgo date={props.event.creationDate} />
            <OverlayTrigger
              trigger="click"
              placement="bottom"
              overlay={EventVersions(props.event)}
              rootClose
            >
              <div style={{ display: 'inline-block' }}>
                <Button bsStyle="link" bsSize="xs">
                  {' '}
                  <Glyphicon glyph="cog" style={{ color: 'white' }} />{' '}
                </Button>
              </div>
            </OverlayTrigger>
          </em>{' '}
        </small>
      </h5>
    );
  }
  return null;
};

NewOrEditEventPanel.propTypes = {
  /* event to edit. Null when a new event is being created. */
  event: PropTypes.object,
  /* investigation identifier */
  investigationId: PropTypes.string,
  /** Function triggered when the user clicks on the save button during event creation or edition*/
  onSaveButtonClicked: PropTypes.func,
  /** Function triggered when the user hits the cancel button */
  onCancelButtonClicked: PropTypes.func,
  /* User who is using this component */
  user: PropTypes.object,
};

export default NewOrEditEventPanel;
