import React from 'react';
import PropTypes from 'prop-types';
import debounce from 'debounce';
import IDUtil from '../../util/IDUtil'; // for generating unique CSS classnames for this component
import SessionStorageHandler from '../../util/SessionStorageHandler';
import { ResourceViewerContext } from './ResourceViewerContext';
import ASR from './contentAnnotationsColumn/ASR';
import Segments from './contentAnnotationsColumn/Segments';
import Info from '../shared/Info';
import _Strings from './_Strings';

// Types
const TYPE_ASR = 'ASR';
const TYPE_SEGMENT = 'Segments';
const TYPE_SUBTITLES = 'Subtitles';

// Views
export const VIEW_LIST = 'List';
export const VIEW_WORDCLOUD = 'Word cloud';
const VIEWS = [VIEW_LIST, VIEW_WORDCLOUD];

// Other
const SESSION_SEARCH_TERM = 'bg__content-annotations-search-term';

export default class ContentAnnotationsColumn extends React.Component {
    static contextType = ResourceViewerContext;

    constructor(props) {
        super(props);

        // get last searchterm from sessionStorage
        const searchTerm = SessionStorageHandler.get(SESSION_SEARCH_TERM, '');

        this.state = {
            type: '',
            view: VIEWS[0],
            searchTerm
        };

        this.searchInputRef = React.createRef();
        this.debounceOnSearch = debounce(this.changeSearch, 200);
    }

    componentDidMount() {
        this.checkCurrentType();
        // Fill search term with query.term, if there is no user defined searchTerm set in
        if (
            !this.state.searchTerm &&
            this.context.query &&
            this.context.query.term
        ) {
            this.setState({ searchTerm: this.context.query.term });
        }
    }

    componentDidUpdate() {
        this.checkCurrentType();
    }

    // check if the current type is available on the resource/mediaobject
    // if not: change it
    checkCurrentType() {
        const types = this.getAvailableTypes();
        if (types.length > 0 && !types.includes(this.state.type)) {
            this.setState({ type: types.length > 0 ? types[0] : '' });
        }
    }

    getActiveContent(type, view, searchTerm) {
        const activeTranscript = this.context.getActiveTranscript(type, true);//fetch them by title
        switch (type) {
            case TYPE_SEGMENT:
                return (
                    <Segments
                        view={view}
                        searchTerm={searchTerm}
                        activeMediaObject={this.context.activeMediaObject}
                        mediaEvents={this.context.mediaEvents}
                    />
                );
            case TYPE_SUBTITLES:
                return (
                    <div>
                        TODO: implement subtitles. Use ASR.jsx as example.
                    </div>
                );
            default: //otherwise return the selected transcript type
                return activeTranscript ? (
                    <ASR
                        view={view}
                        searchTerm={searchTerm}
                        resource={this.context.resource}
                        activeMediaObject={this.context.activeMediaObject}
                        mediaEvents={this.context.mediaEvents}
                        transcript={activeTranscript} //could be different types of transcripts (ASR, Voting, Agenda Points...)
                    />
                ) : null;
        }
    }

    changeType = e => {
        this.setState({ type: e.target.value });
    };

    changeView = e => {
        this.setState({ view: e.target.value });
    };

    changeSearch = () => {
        // use the ref so we use this as debounced function
        this.setSearchTerm(this.searchInputRef.current.value);
    };

    clearSearch = () => {
        // manually empty the input value as it is only assigned with attr:defaultValue
        this.searchInputRef.current.value = '';
        this.setSearchTerm('');
    };

    setSearchTerm = searchTerm => {
        // update state
        this.setState({ searchTerm });

        // store searchTerm to session
        SessionStorageHandler.set(SESSION_SEARCH_TERM, searchTerm);
    };

    // Return types available in current context
    //FIXME this should not be done here, but in the collectionConfig!!
    getAvailableTypes = () => {
        const types = [];
        // Segments
        if (
            this.context.activeMediaObject &&
            this.context.activeMediaObject.segments
        ) {
            types.push(TYPE_SEGMENT);
        }

        // Subtitles
        // TODO: which field?
        if (false) {
            types.push(TYPE_SUBTITLES);
        }

        //loop through the transcripts of the resource and add them as types
        const transcripts = this.context.getActiveTranscripts();
        if(transcripts) {
            transcripts.forEach(transcript => {
                types.push(transcript.title);
            });
        }

        return types;
    };

    render() {
        const activeContent = this.getActiveContent(this.state.type, this.state.view, this.state.searchTerm);

        // Types
        const types = this.getAvailableTypes();

        // No types available? Render a notification
        if (types.length === 0) {
            return (
                <div
                    className={IDUtil.cssClassName(
                        'content-annotations-column'
                    )}
                >
                    <div className="error-message">
                        No content annotations available
                        <Info
                            className="primary"
                            id={'info_content_annotations'}
                            text={
                                'There are no content annotations available on the selected resource or the active media object'
                            }
                        />
                    </div>
                </div>
            );
        }

        const typeSelector = (
            <select value={this.state.type} onChange={this.changeType}>
                {types.map(type => (
                    <option value={type} key={type}>
                        {type}
                    </option>
                ))}
            </select>
        );

        // Views
        const viewSelector = (
            <select value={this.state.view} onChange={this.changeView}>
                {VIEWS.map(type => (
                    <option value={type} key={type}>
                        {type}
                    </option>
                ))}
            </select>
        );

        return (
            <div className={IDUtil.cssClassName('content-annotations-column')}>
                <div className="type-selector">
                    <strong>Type:</strong>
                    {typeSelector}
                    <Info
                        className="primary"
                        id={'info_content_annotations'}
                        text={_Strings.CONTENT_ANNOTATIONS_TYPE_HELP}
                    />
                </div>

                <div className="filter">
                    <strong>View:</strong>
                    {viewSelector}
                    <input
                        placeholder="Search..."
                        defaultValue={this.state.searchTerm}
                        onChange={this.debounceOnSearch}
                        onKeyUp={this.debounceOnSearch} // required to register empty field? :S
                        ref={this.searchInputRef}
                    />
                    {this.state.searchTerm && (
                        <div
                            className="clear"
                            title="Clear search"
                            onClick={this.clearSearch}
                        />
                    )}
                </div>

                {activeContent}
            </div>
        );
    }
}
