import React from 'react';
import PropTypes from 'prop-types';
import { Panel, Label, Glyphicon, OverlayTrigger, Tooltip, Grid, Row, Col, Button, InputGroup, FormControl } from 'react-bootstrap';
import EventHeader from './EventHeader';
import EventFooter from './EventFooter';
import TagContainer from '../../containers/Logbook/TagContainer';
import EventContentPanel from './EventContentPanel';
import { EDIT_EVENT_INVISIBLE, NEW_EVENT_CONTEXT, EDIT_EVENT_CONTEXT, NEW_EVENT_INVISIBLE, EVENT_CATEGORY_COMMENT, ANNOTATION, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT } from '../../constants/EventTypes';
import EventHistory from './EventHistory';
import { getEventCreationDate, getEventHistoryCreationDate, getOriginalEvent, getPreviousVersionNumber } from '../../helpers/EventHelpers';
import _ from 'lodash';
import LabeledElement from './LabeledElement';

/**
 * 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
        }

        this.createEvent = this.createEvent.bind(this);
        this.onCancelButtonClicked = this.onCancelButtonClicked.bind(this);
        this.onEventModified = this.onEventModified.bind(this);
        this.onSaveButtonClicked = this.onSaveButtonClicked.bind(this);
        this.onSuccessfullyCreated = this.onSuccessfullyCreated.bind(this);
        this.onSuccessfullyUpdated = this.onSuccessfullyUpdated.bind(this);
        this.setTagContainer = this.setTagContainer.bind(this);
        this.setTitleInput = this.setTitleInput.bind(this);
        this.updateEvent = this.updateEvent.bind(this);
    }
    render() {
        let { event, user, context, investigationId } = this.props;
        return (
            <Panel bsStyle='primary' style={{ marginBottom: '0px', height: '100%', position: 'relative' }}>
                <EventHeader context={context} />
                <div id='refForEditorHeightCalculation' style={{ position: 'absolute', top: '41px', bottom: '100px', width: '100%' }} >
                    <div id='editorContainer' style={{ padding: '1px', position: 'absolute', top: '0px', bottom: '34px', left: '0px', right: '2px' }}>
                        <EventContentPanel
                            context={context}
                            event={event}
                            investigationId={investigationId}
                            onEventModified={this.onEventModified}
                            user={user}
                        />
                        <Grid fluid style={{ height: '100px' }}>

                            <Row>
                                <Col xs={4}> <CreationDate event={event} /> </Col>
                                <Col xs={4}> <CommentBy event={event} /> </Col>
                                <Col xs={3}> <EventHistory event={event} /> </Col>
                                {/* <Col xs={1}>
                                    <Button bsSize='xsmall' onClick={() => this.setState({ optionPanelDecollaped: !this.state.optionPanelDecollaped })}>
                                        <Glyphicon glyph='option-vertical' />
                                    </Button>
                                </Col> */}
                            </Row>
                            <Row>
                                <Col xs={12} style={{ paddingTop: '8px', paddingBottom: '8px' }}>
                                    <div style={{ display: 'flex' }}>
                                        <div style={{ flex: '0 0 70px' }}>
                                            <Label style={{ margin: '0px 6px 0px 0px', paddingRight: '2px' }}> Tags </Label>
                                            <OverlayTrigger
                                                placement='top'
                                                overlay={<Tooltip id='tooltip'> <p> Manage tags </p> </Tooltip>}>
                                                <a href={"/investigation/" + this.props.investigationId + "/events/tagManager"} target="_blank" style={{ fontSize: '12px' }}> <Glyphicon glyph='cog' /> </a>
                                            </OverlayTrigger>
                                        </div>
                                        <div style={{ flex: '1 1 100px' }}>
                                            <TagContainer
                                                canEnableSaveButton={this.onEventModified}
                                                context={context}
                                                event={event}
                                                investigationId={this.props.investigationId}
                                                setTagContainer={this.setTagContainer}
                                            />
                                        </div>
                                    </div>






                                    {/* <Panel id="optionPanel" style={{ border: 'none', marginBottom: '0px' }} expanded={this.state.optionPanelDecollaped}>
                                        <Panel.Collapse>
                                            <LabeledElement type='input' data={event ? event.title : null} labelText='title' onEventModified={this.onEventModified} setTitleInput={this.setTitleInput} tooltip='title of the event' />
                                        </Panel.Collapse>
                                    </Panel> */}
                                </Col>
                            </Row>
                        </Grid>
                    </div>

                </div>
                <div style={{ position: 'absolute', bottom: '0px', width: '100%' }}>
                    <EventFooter
                        isSaveButtonEnabled={this.state.isSaveButtonEnabled}
                        onCancelButtonClicked={() => this.onCancelButtonClicked()}
                        onSaveButtonClicked={() => this.onSaveButtonClicked()} />
                </div>
            </Panel >
        )
    }

    /**
    * Callback method called when current event has been modified by user. This could original from a key press in the editor, a change in tags, ...
    * @param {*} change the object representing the change
    * -1- hasText boolean which indicates whether the editor content has text or not; not null
    * -2- currentTextEqualsOriginal, boolean, which indicates whether the current content is the same as the original content; not null
    */
    onEventModified(change) {
        let hasEventTitleChangedFromItsOriginalValue = this.inputTitle && this.props.event && this.inputTitle.props.value !== this.props.event.title;

        let hasEventTagsChangedFromItsOriginalValue = this.tagContainer && this.props.event &&
            !(_.isEqual(this.tagContainer.state.selectedTags.map((tag) => tag._id), this.props.event.tag));

        if (hasEventTitleChangedFromItsOriginalValue || hasEventTagsChangedFromItsOriginalValue) {
            /* title is not the same as original. can save (even with no content) */
            if (this.state.isSaveButtonEnabled !== true) { this.setState({ isSaveButtonEnabled: true }); }
        } else {
            /* title is the same as original */
            if (change) {
                /* triggered from the editor */
                let hasText = null;
                let currentTextEqualsOriginal = null;
                if ('hasText' in change) { hasText = change.hasText; };
                if ('currentTextEqualsOriginal' in change) {
                    currentTextEqualsOriginal = change.currentTextEqualsOriginal;
                };
                if (!hasText) {
                    // there is no text in the editor
                    if (this.state.isEditorContentValid !== false) {
                        this.setState({ isEditorContentValid: false, isSaveButtonEnabled: false });
                    };
                } else {
                    // there is text in the editor
                    if (currentTextEqualsOriginal === undefined || currentTextEqualsOriginal === null) {
                        if (this.state.isEditorContentValid !== false) {
                            this.setState({ isEditorContentValid: false, isSaveButtonEnabled: false });
                        };
                    } else if (currentTextEqualsOriginal) {
                        // current text in the editor equals the original text
                        if (this.state.isEditorContentValid !== false) {
                            this.setState({ isEditorContentValid: false, isSaveButtonEnabled: false });
                        };
                    } else if (this.state.isEditorContentValid !== true) {
                        this.setState({ isEditorContentValid: true, isSaveButtonEnabled: !hasEventTitleChangedFromItsOriginalValue });
                    };
                };
            } else if (!this.state.isEditorContentValid) {
                /* Editor content is not valid. Can not save */
                if (this.state.isSaveButtonEnabled !== false) { this.setState({ isSaveButtonEnabled: false }); }
            };
        };
    }

    /**
     * Callback function triggered when the user clicks on the cancel button
     */
    onCancelButtonClicked() {
        if (this.props.context) {
            if (this.props.context === NEW_EVENT_CONTEXT) {
                localStorage.removeItem('plainText');
                localStorage.removeItem('HTMLText');
                this.props.setNewEventVisibility(NEW_EVENT_INVISIBLE);

            } else if (this.props.context === EDIT_EVENT_CONTEXT) {
                this.props.setEditEventVisibility(EDIT_EVENT_INVISIBLE)
            }
        }
    }

    /**
     * Callback function triggered when the user click the save button while an event is being created or updated.
     */
    onSaveButtonClicked() {
        if (this.props.context) {
            if (this.props.context === NEW_EVENT_CONTEXT) {
                this.createEvent();
            } else if (this.props.context === EDIT_EVENT_CONTEXT) {
                this.updateEvent();
            }
        }
    }

    /** 
    * Callback triggered when the event has been successfully created on the server side
    */
    onSuccessfullyCreated() {
        this.props.onNewEventUploaded();
    }

    /** 
     * Callback triggered when the event has been successfully updated on the server side
     */
    onSuccessfullyUpdated(updatedEvent) {
        this.props.onEventUpdated(updatedEvent);
    }


    /**
     * Callback function used to set the tagcontainer instance to a class instance variable in order to access data stored within the tag container 
     */
    setTagContainer(element) {
        this.tagContainer = element;
    }

    /** Callback function used to set the titleInput instance to a class instance variable inorder to access data stored within the title input */
    setTitleInput(element) {
        this.inputTitle = element;
    }

    /**
    * Creates an event. It's a request to the server which may fail.
    */
    createEvent() {
        let currentTagIds = this.tagContainer.state.selectedTags.map((tag) => tag._id);

        let newEvent = {
            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: '', //this.inputTitle.value,
            tag: currentTagIds,
            type: ANNOTATION,
            username: this.props.user.username,
        }

        this.props.createEvent(newEvent, this.props.user.sessionId, this.props.investigationId, this.onSuccessfullyCreated)
    }

    /**
     * Updates an event. It's a request to the server which may fail.
     */
    updateEvent() {
        let { investigationId, event, user } = this.props;

        // get tags
        let currentTagIds = this.tagContainer.state.selectedTags.map((tag) => tag._id);

        let updatedEvent = {
            _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,
            tags: currentTagIds,
            title: (this.inputTitle && this.inputTitle.props) ? this.inputTitle.props.value : null,
            username: user.username,
            previousVersionEvent: event._id
        };
        this.props.updateEvent(updatedEvent, user.sessionId, investigationId, this.onSuccessfullyUpdated);
    }
}

NewOrEditEventPanel.propTypes = {
    /* context in which this component is used */
    context: PropTypes.oneOf([ NEW_EVENT_CONTEXT, EDIT_EVENT_CONTEXT ]),
    /* event to edit. Null when a new event is beaing created. */
    event: PropTypes.object,
    /* investigation identifier */
    investigationId: PropTypes.string,
    /* callback function triggered after a event was successfully updated  on the server */
    onEventUpdated: PropTypes.func,
    // toggleMode={this.toggleMode}
    /* callback function used to change the visibility of the modal */
    setEditEventVisibility: PropTypes.func,
    /* User who is using this component */
    user: PropTypes.object,
    /* Callback used to request an event update on the server side */
    updateEvent: PropTypes.func
}

/** React component which represents the creation date part. */
const CreationDate = (props) => {
    if (props.event) {
        return (<LabeledElement data={getEventCreationDate(getOriginalEvent(props.event))} hasNoData={false} type='text' labelText='Creation date' tooltip={<p> Event created on {getEventHistoryCreationDate(getOriginalEvent(props.event))} </p>} />);
    }
    return null;
}

/**
 * React component which represents the commentBy part.
* @param {*} props
            */
const CommentBy = (props) => {
    if (props.event) {
        if (getPreviousVersionNumber(props.event) === 0) {
            return (<LabeledElement data={props.event.username} hasNoData={false} type='text' labelText='Created by' tooltip='Author of the event' />);
        };
        if (getPreviousVersionNumber(props.event) !== 0) {
            return (<LabeledElement data={props.event.username} hasNoData={false} type='text' labelText='Commented by' tooltip='Author of the comment' />);
        };
    }
    return null;
};

export default NewOrEditEventPanel;