import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import { Doc } from '../../../fields/Doc';
import { Cast, DocCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { SelectionManager } from '../../util/SelectionManager';
import { SettingsManager } from '../../util/SettingsManager';
import { undoBatch } from '../../util/UndoManager';
import { DocumentView, DocumentViewInternal, OpenWhere } from '../nodes/DocumentView';
import { LinkDocPreview } from '../nodes/LinkDocPreview';
import './LinkMenuItem.scss';
import React = require('react');

interface LinkMenuItemProps {
    groupType: string;
    linkDoc: Doc;
    docView: DocumentView;
    sourceDoc: Doc;
    destinationDoc: Doc;
    clearLinkEditor?: () => void;
    menuRef: React.Ref<HTMLDivElement>;
    itemHandler?: (doc: Doc) => void;
}

// drag links and drop link targets (embedding them if needed)
export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: DocumentView, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) {
    const draggedDocs = (specificLinks ? specificLinks : LinkManager.Links(sourceDoc)).map(link => LinkManager.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[];

    if (draggedDocs.length) {
        const moddrag: Doc[] = [];
        for (const draggedDoc of draggedDocs) {
            const doc = await Cast(draggedDoc.annotationOn, Doc);
            if (doc) moddrag.push(doc);
        }

        const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
        dragData.canEmbed = true;
        dragData.dropAction = 'embed';

        DragManager.StartDocumentDrag([dragEle], dragData, downX, downY, undefined);
    }
}

@observer
export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
    private _drag = React.createRef<HTMLDivElement>();

    _editRef = React.createRef<HTMLDivElement>();

    @observable private _showMore: boolean = false;
    @action toggleShowMore(e: React.PointerEvent) {
        e.stopPropagation();
        this._showMore = !this._showMore;
    }

    @computed get sourceAnchor() {
        const ldoc = this.props.linkDoc;
        if (this.props.sourceDoc !== ldoc.link_anchor_1 && this.props.sourceDoc !== ldoc.link_anchor_2) {
            if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_1).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.link_anchor_1);
            if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_2).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.link_anchor_2);
        }
        return this.props.sourceDoc;
    }

    onEdit = (e: React.PointerEvent) => {
        setupMoveUpEvents(
            this,
            e,
            e => {
                const dragData = new DragManager.DocumentDragData([this.props.linkDoc], 'embed');
                dragData.dropPropertiesToRemove = ['hidden'];
                DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y);
                return true;
            },
            emptyFunction,
            action(() => {
                const trail = DocCast(this.props.docView.rootDoc.presentationTrail);
                if (trail) {
                    Doc.ActivePresentation = trail;
                    DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight);
                } else {
                    SelectionManager.SelectView(this.props.docView, false);
                    LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
                    LinkManager.currentLinkAnchor = LinkManager.currentLink ? this.sourceAnchor : undefined;

                    if ((SettingsManager.propertiesWidth ?? 0) < 100) {
                        setTimeout(action(() => (SettingsManager.propertiesWidth = 250)));
                    }
                }
            })
        );
    };

    onLinkButtonDown = (e: React.PointerEvent): void => {
        setupMoveUpEvents(
            this,
            e,
            e => {
                const eleClone: any = this._drag.current!.cloneNode(true);
                eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`;
                StartLinkTargetsDrag(eleClone, this.props.docView, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]);
                this.props.clearLinkEditor?.();
                return true;
            },
            emptyFunction,
            () => {
                this.props.clearLinkEditor?.();
                if (this.props.itemHandler) {
                    this.props.itemHandler?.(this.props.linkDoc);
                } else {
                    const focusDoc =
                        Cast(this.props.linkDoc.link_anchor_1, Doc, null)?.annotationOn === this.props.sourceDoc
                            ? Cast(this.props.linkDoc.link_anchor_1, Doc, null)
                            : Cast(this.props.linkDoc.link_anchor_2, Doc, null)?.annotationOn === this.props.sourceDoc
                            ? Cast(this.props.linkDoc.link_anchor_12, Doc, null)
                            : undefined;

                    if (focusDoc) this.props.docView.props.focus(focusDoc, { instant: true });
                    LinkFollower.FollowLink(this.props.linkDoc, this.props.sourceDoc, false);
                }
            }
        );
    };

    deleteLink = (e: React.PointerEvent): void => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => LinkManager.Instance.deleteLink(this.props.linkDoc))));
    @observable _hover = false;
    render() {
        const destinationIcon = Doc.toIcon(this.props.destinationDoc) as any as IconProp;

        const title = StrCast(this.props.destinationDoc.title).length > 18 ? StrCast(this.props.destinationDoc.title).substr(0, 14) + '...' : this.props.destinationDoc.title;

        const source =
            this.props.sourceDoc.type === DocumentType.RTF
                ? this.props.linkDoc.storedText
                    ? StrCast(this.props.linkDoc.storedText).length > 17
                        ? StrCast(this.props.linkDoc.storedText).substr(0, 18)
                        : this.props.linkDoc.storedText
                    : undefined
                : undefined;

        return (
            <div
                className="linkMenu-item"
                onPointerEnter={action(e => (this._hover = true))}
                onPointerLeave={action(e => (this._hover = false))}
                style={{
                    fontSize: this._hover ? 'larger' : undefined,
                    fontWeight: this._hover ? 'bold' : undefined,
                    background: LinkManager.currentLink === this.props.linkDoc ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                }}>
                <div className="linkMenu-item-content expand-two">
                    <div
                        ref={this._drag}
                        className="linkMenu-name" //title="drag to view target. click to customize."
                        onPointerDown={this.onLinkButtonDown}>
                        <div className="linkMenu-item-buttons">
                            <Tooltip title={<div className="dash-tooltip">Edit Link</div>}>
                                <div className="button" ref={this._editRef} onPointerDown={this.onEdit} onClick={e => e.stopPropagation()}>
                                    <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" />
                                </div>
                            </Tooltip>
                        </div>
                        <div
                            className="linkMenu-text"
                            onPointerLeave={LinkDocPreview.Clear}
                            onPointerEnter={e =>
                                this.props.linkDoc &&
                                this.props.clearLinkEditor &&
                                LinkDocPreview.SetLinkInfo({
                                    docProps: this.props.docView.props,
                                    linkSrc: this.props.sourceDoc,
                                    linkDoc: this.props.linkDoc,
                                    showHeader: false,
                                    location: [(this._drag.current?.getBoundingClientRect().left ?? 100) + 40, (this._drag.current?.getBoundingClientRect().top ?? e.clientY) + 25],
                                    noPreview: false,
                                })
                            }>
                            {source ? (
                                <p className="linkMenu-source-title">
                                    {' '}
                                    <b>Source: {StrCast(source)}</b>
                                </p>
                            ) : null}
                            <div className="linkMenu-title-wrapper">
                                <div className="destination-icon-wrapper">
                                    <FontAwesomeIcon className="destination-icon" icon={destinationIcon} size="sm" />
                                </div>
                                <p className="linkMenu-destination-title">
                                    {this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? 'Annotation in' : ''} {StrCast(title)}
                                </p>
                            </div>
                            {!this.props.linkDoc.link_description ? null : <p className="linkMenu-description">{StrCast(this.props.linkDoc.link_description)}</p>}
                        </div>

                        <div className="linkMenu-item-buttons">
                            <Tooltip title={<div className="dash-tooltip">Delete Link</div>}>
                                <div className="linkMenu-deleteButton" onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}>
                                    <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" />
                                </div>
                            </Tooltip>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}
