import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import IDUtil from '../../../util/IDUtil';

import { SELECTION_TEMPORAL, SELECTION_SPATIAL } from '../../../util/AnnotationConstants';
import { MSAnnotationUtil } from '../AnnotationClient';
import { getSegmentTitle } from '../AnnotationHelpers';
import { ResourceViewerContext } from '../ResourceViewerContext';

import TimeInput from './TimeInput';
import Strings from '../_Strings';

export default class SegmentHeader extends React.PureComponent {
    static contextType = ResourceViewerContext;

    constructor(props) {
        super(props);

        this.state = {
            edit: false,
        };

        this.editSelection = null;
    }

    componentDidUpdate() {
        // stop edit mode when not highlighted
        if (!this.props.highlight && this.state.edit) {
            this.stopEdit();
        }
    }

    // INLINE EDITING

    // return an update function for editing a temporal selection
    updateTemporalEditSelection = (field) => {
        return (value) => {
            this.editSelection[field] = value;
        };
    };

    // return an update function for editing a spatial selection
    updateSpatialEditSelection = (field) => {
        return (e) => {
            this.editSelection.rect[field] = e.target.value;
        };
    };

    // return a save/setter function for the
    saveSelection = (segment) => {
        return () => {
            const selection = Object.assign({}, this.editSelection);
            this.props.updateSegment(segment, selection);

            this.stopEdit();
        };
    };

    // delete segment
    deleteSegment = (segment) => {
        return (e) => {
            e.stopPropagation();
            if (!confirm(Strings.SEGMENT_DELETE_CONFIRM)) {
                return;
            }
            // sending null to the update function results in the segment getting deleted
            this.props.updateSegment(segment, null);

            this.stopEdit();
        };
    };

    onTitleClick = (e) => {
        e.stopPropagation();
        if (!this.props.highlight) {
            this.props.onSelect(this.props.segment);
        }
    };

    onTitleDoubleClick = (e) => {
        e.stopPropagation();
        this.setState({ edit: true });
    };

    stopEdit = () => {
        this.setState({ edit: false });
    };

    stopEvent = (e) => {
        e.stopPropagation();
    };

    // Render form for inline editing
    renderForm = (segment) => {
        // Check for valid selection
        const selection = MSAnnotationUtil.extractSelectionFromTarget(
            segment.target
        );
        if (!selection) {
            console.warn("Could not find selection for target", segment.target);
            return null;
        }

        // store selection that is being edited
        this.editSelection = selection;

        switch (selection.type) {
            case SELECTION_TEMPORAL:
                return (
                    <div
                        className="form temporal"
                        onClick={this.stopEvent}
                        title={Strings.SEGMENT_TITLE_EDIT_SUBMIT}
                    >
                        <TimeInput
                            time={selection.start}
                            onUpdate={this.updateTemporalEditSelection("start")}
                            onFinish={this.saveSelection(segment)}
                        />
                        {" - "}
                        <TimeInput
                            time={selection.end}
                            onUpdate={this.updateTemporalEditSelection("end")}
                            onFinish={this.saveSelection(segment)}
                        />
                    </div>
                );
            case SELECTION_SPATIAL:
                const inputs = ["x", "y", "w", "h"].map((v) => (
                    <span key={v}>
                        <input
                            type="number"
                            ref={this[v]}
                            defaultValue={selection.rect[v]}
                            onFocus={(e) => {
                                e.target.select();
                            }}
                            onChange={this.updateSpatialEditSelection(v)}
                            onKeyDown={(e) => {
                                if (e.keyCode == 13) {
                                    this.saveSelection(segment)();
                                }
                            }}
                        />
                    </span>
                ));

                return (
                    <div
                        className="form spatial"
                        onClick={this.stopEvent}
                        title={Strings.SEGMENT_TITLE_EDIT_SUBMIT}
                    >
                        {inputs}
                    </div>
                );
            default:
                return null;
        }
    };

    playSegment = (startTime) => {
        if (startTime && this.context.playerAPI) {
            const resourceStart =
                this.context.activeMediaObject &&
                this.context.activeMediaObject.resourceStart
                    ? this.context.activeMediaObject.resourceStart + startTime
                    : startTime;

            this.context.playerAPI.seek(resourceStart);
        }
    };

    render() {
        // Delete button
        const deleteButton = (
            <span
                className="delete"
                title={Strings.SEGMENT_DELETE_TITLE}
                onClick={this.deleteSegment(this.props.segment)}
            />
        );

        // content is a titletext or an editable form
        const content = this.state.edit ? (
            // edit mode
            this.renderForm(this.props.segment)
        ) : (
            // view mode
            <span
                className="title"
                title={Strings.SEGMENT_TITLE_EDIT}
                onClick={this.onTitleClick}
                onDoubleClick={this.onTitleDoubleClick}
            >
                {getSegmentTitle(this.props.segment, this.props.activeTypes)}
            </span>
        );

        const startTime =
            this.props.segment.target.selector &&
            this.props.segment.target.selector.refinedBy
                ? this.props.segment.target.selector.refinedBy.start
                : null;

        return (
            <div
                className={classNames(IDUtil.cssClassName("segment-header"), {
                    active: this.props.active,
                    highlight: this.props.highlight,
                })}
                onClick={this.props.onToggle}
            >
                <span
                    className="play-segment"
                    onClick={(e) => {
                        this.playSegment(startTime);
                        e.stopPropagation();
                    }}
                >
                    <i className="fas fa-play" title="Play segment" />
                </span>
                <span className="left">{content}</span>
                <span className="count">
                    {this.props.segment.body
                        ? this.props.segment.body.length
                        : 0}
                </span>
                {deleteButton}
            </div>
        );
    }
}

SegmentHeader.propTypes = {
    segment: PropTypes.object.isRequired,
    active: PropTypes.bool.isRequired,
    highlight: PropTypes.bool.isRequired,
    onToggle: PropTypes.func.isRequired,
    onSelect: PropTypes.func.isRequired,
    updateSegment: PropTypes.func.isRequired,
    activeTypes: PropTypes.array.isRequired,
};
