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

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

import Classification from './Types/Classification';
import Comment from './Types/Comment';
import Link from './Types/Link';
import Metadata from './Types/Metadata';

import TypeHeader from './TypeHeader';

import ClassificationEditor from './ClassificationForm';
import CommentEditor from './CommentForm';
import LinkForm from './LinkForm';
import MetadataForm from './MetadataForm';

import { ANNOTATION_TYPE } from './Constants';

export default class AnnotationType extends React.PureComponent {
    constructor(props) {
        super(props);

        // initial state
        this.state = {
            active: false,
            showForm: false
        };
    }

    // Delete the given annotations using the annotationClient
    deleteAnnotation = annotation => {
        console.debug('Delete annotation', annotation);

        // Get index of given annotation
        let index = -1;
        if (
            !this.props.annotations.some((a, i) => {
                if (a.annotationId == annotation.annotationId) {
                    index = i;
                    return true;
                }
                return false;
            })
        ) {
            console.error('Annotation not in list, can not be deleted');
            return;
        }

        // Get motivation/ type

        this.props.annotationClient.removeBodyElement(
            this.props.type,
            index,
            true,
            true,
            this.props.targetAnnotation
        );
    };

    /* ---------------------------------- UI FUNCTIONS -------------------------------- */

    // Create a target annotation for the current target
    // This way there is a body to which we can add the type annotations
    createTargetAnnotation = () => {
        // create new annotation
        const annotation = this.props.annotationClient.newAnnotation(
            this.props.target,
            false
        );
        this.props.annotationClient.edit(annotation);
        this.props.annotationClient.save();
    };

    // Toggle form visibility
    // Optionally create a target (root) annotation
    toggleForm = () => {
        this.setState({ showForm: !this.state.showForm }, () => {
            // if we show the form, check for a target annotation
            // if it does not exist yet; create one
            if (!this.props.targetAnnotation) {
                this.createTargetAnnotation();
            }
        });
    };

    // /* ---------------------------------- RENDER FUNCTIONS -------------------------------- */

    // Render an annotation, based on the given type
    renderAnnotation = (
        type,
        annotation,
        key,
        targetAnnotation,
        annotationClient
    ) => {
        const defaultProps = {
            key,
            delete: this.deleteAnnotation,
            annotationClient,
            targetAnnotation
        };
        switch (type) {
            case ANNOTATION_TYPE.CLASSIFICATION:
                return (
                    <Classification
                        classification={annotation}
                        {...defaultProps}
                    />
                );
            case ANNOTATION_TYPE.COMMENT:
                return <Comment comment={annotation} {...defaultProps} />;
            case ANNOTATION_TYPE.LINK:
                return <Link link={annotation} {...defaultProps} />;
            case ANNOTATION_TYPE.METADATA:
                return <Metadata metadata={annotation} {...defaultProps} />;
            default:
                return <span key={key}>{type} - not implemented.</span>;
        }
    };

    // Render the form for the given annotation type
    renderForm(type, annotation, annotationClient) {
        const props = {
            annotationClient,
            annotation
        };
        switch (type) {
            case ANNOTATION_TYPE.CLASSIFICATION:
                return <ClassificationEditor {...props} />;
            case ANNOTATION_TYPE.COMMENT:
                return <CommentEditor {...props} />;
            case ANNOTATION_TYPE.LINK:
                return <LinkForm {...props} />;
            case ANNOTATION_TYPE.METADATA:
                return <MetadataForm onSave={this.toggleForm} {...props} />;
            default:
                return <span>{type} - not implemented.</span>;
        }
    }

    render() {
        const type = this.props.type;

        // type header
        const header = (
            <TypeHeader
                type={type}
                showForm={this.state.showForm}
                toggleForm={this.toggleForm}
            />
        );

        // the annotation content
        const annotations = (
            <div className={'type-annotations'}>
                {this.props.annotations.map((annotation, index) =>
                    this.renderAnnotation(
                        type,
                        annotation,
                        index,
                        this.props.targetAnnotation,
                        this.props.annotationClient
                    )
                )}
            </div>
        );

        // type specific form
        const form =
            this.state.showForm && this.props.targetAnnotation ? (
                <div className="annotation-form">
                    {this.renderForm(
                        type,
                        this.props.targetAnnotation,
                        this.props.annotationClient
                    )}
                </div>
            ) : null;

        return (
            <div
                className={classNames(
                    IDUtil.cssClassName('annotation-type'),
                    'type-' + type,
                    { 'has-content': this.props.annotations.length > 0 }
                )}
            >
                {header}
                {form}
                {annotations}
            </div>
        );
    }
}

AnnotationType.propTypes = {
    type: PropTypes.string.isRequired,
    target: PropTypes.string.isRequired,
    targetAnnotation: PropTypes.object,
    annotationClient: PropTypes.object.isRequired,
    annotations: PropTypes.array.isRequired
};
