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 "../../../util/AnnotationConstants";

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

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

    // Delete the given annotations using the annotationClient
    deleteAnnotation = (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
        );
        if (annotation) {
            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, deleteAnnotation) {
        const props = {
            annotationClient,
            annotation,
            deleteAnnotation,
        };
        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,
                        this.deleteAnnotation
                    )}
                </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,
    showForm: PropTypes.bool.isRequired,
};
