import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
import { IconButton } from 'browndash-components';
import { action, computed, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { FaUndo } from 'react-icons/fa';
import { Utils, aggregateBounds, emptyFunction, numberValue, returnFalse, setupMoveUpEvents } from '../../Utils';
import { DateField } from '../../fields/DateField';
import { Doc, DocListCast, Field } from '../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, DocData, Height, Width } from '../../fields/DocSymbols';
import { InkField } from '../../fields/InkField';
import { RichTextField } from '../../fields/RichTextField';
import { ScriptField } from '../../fields/ScriptField';
import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { GetEffectiveAcl, normalizeEmail } from '../../fields/util';
import { DocumentType } from '../documents/DocumentTypes';
import { Docs } from '../documents/Documents';
import { DocumentManager } from '../util/DocumentManager';
import { DragManager } from '../util/DragManager';
import { LinkFollower } from '../util/LinkFollower';
import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
import { DocumentButtonBar } from './DocumentButtonBar';
import './DocumentDecorations.scss';
import { InkStrokeProperties } from './InkStrokeProperties';
import { InkingStroke } from './InkingStroke';
import { LightboxView } from './LightboxView';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { Colors } from './global/globalEnums';
import { DocumentView, OpenWhereMod } from './nodes/DocumentView';
import { ImageBox } from './nodes/ImageBox';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import React = require('react');
import _ = require('lodash');

@observer
export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> {
    static Instance: DocumentDecorations;
    private _resizeHdlId = '';
    private _keyinput = React.createRef<HTMLInputElement>();
    private _resizeBorderWidth = 16;
    private _linkBoxHeight = 20 + 3; // link button height + margin
    private _titleHeight = 20;
    private _resizeUndo?: UndoManager.Batch;
    private _offX = 0;
    _offY = 0; // offset from click pt to inner edge of resize border
    private _snapX = 0;
    _snapY = 0; // last snapped location of resize border
    private _dragHeights = new Map<Doc, { start: number; lowest: number }>();
    private _inkDragDocs: { doc: Doc; x: number; y: number; width: number; height: number }[] = [];

    @observable private _accumulatedTitle = '';
    @observable private _titleControlString: string = '#title';
    @observable private _editingTitle = false;
    @observable private _hidden = false;
    @observable public AddToSelection = false; // if Shift is pressed, then this should be set so that clicking on the selection background is ignored so overlapped documents can be added to the selection set.
    @observable public Interacting = false;
    @observable public pushIcon: IconProp = 'arrow-alt-circle-up';
    @observable public pullIcon: IconProp = 'arrow-alt-circle-down';
    @observable public pullColor: string = 'white';
    @observable private _isRotating: boolean = false;
    @observable private _isRounding: boolean = false;
    @observable private _isResizing: boolean = false;

    constructor(props: any) {
        super(props);
        DocumentDecorations.Instance = this;
        reaction(
            () => SelectionManager.Views().slice(),
            action(docs => {
                this._showNothing = !DocumentView.LongPress && docs.length === 1; // show decorations if multiple docs are selected or we're long pressing
                this._editingTitle = false;
            })
        );
        document.addEventListener(
            // show decorations whenever pointer moves outside of selection bounds.
            'pointermove',
            action(e => {
                if (this.Bounds.x !== Number.MAX_VALUE && (this.Bounds.x > e.clientX || this.Bounds.r < e.clientX || this.Bounds.y > e.clientY || this.Bounds.b < e.clientY)) {
                    this._showNothing = false;
                }
            })
        );
    }

    @computed
    get Bounds() {
        if (LinkFollower.IsFollowing) return { x: 0, y: 0, r: 0, b: 0 };
        const views = SelectionManager.Views();
        return views
            .filter(dv => dv.props.renderDepth > 0)
            .map(dv => dv.getBounds())
            .reduce(
                (bounds, rect) =>
                    !rect
                        ? bounds
                        : {
                              x: Math.min(rect.left, bounds.x),
                              y: Math.min(rect.top, bounds.y),
                              r: Math.max(rect.right, bounds.r),
                              b: Math.max(rect.bottom, bounds.b),
                              c: views.length === 1 ? rect.center : undefined,
                          },
                { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE, c: undefined as { X: number; Y: number } | undefined }
            );
    }

    @action
    titleBlur = () => {
        this._editingTitle = false;
        if (this._accumulatedTitle.startsWith('#') || this._accumulatedTitle.startsWith('=')) {
            this._titleControlString = this._accumulatedTitle;
        } else if (this._titleControlString.startsWith('#')) {
            const titleFieldKey = this._titleControlString.substring(1);
            UndoManager.RunInBatch(
                () =>
                    titleFieldKey &&
                    SelectionManager.Views().forEach(d => {
                        if (titleFieldKey === 'title') {
                            d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-');
                            if (StrCast(d.rootDoc.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) {
                                Doc.RemoveDocFromList(Doc.MyPublishedDocs, undefined, d.rootDoc);
                            }
                            if (!StrCast(d.rootDoc.title).startsWith('@') && this._accumulatedTitle.startsWith('@')) {
                                Doc.AddDocToList(Doc.MyPublishedDocs, undefined, d.rootDoc);
                            }
                        }
                        //@ts-ignore
                        const titleField = +this._accumulatedTitle == this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle;

                        if (titleField.toString().startsWith('<this>')) {
                            const title = titleField.toString().replace(/<this>\.?/, '');
                            const curKey = Doc.LayoutFieldKey(d.rootDoc);
                            if (curKey !== title) {
                                if (title) {
                                    if (d.dataDoc[title] === undefined || d.dataDoc[title] instanceof RichTextField || typeof d.dataDoc[title] === 'string') {
                                        d.rootDoc.layout_fieldKey = `layout_${title}`;
                                        d.rootDoc[`layout_${title}`] = FormattedTextBox.LayoutString(title);
                                        d.rootDoc[`${title}_nativeWidth`] = d.rootDoc[`${title}_nativeHeight`] = 0;
                                    }
                                } else {
                                    d.rootDoc.layout_fieldKey = undefined;
                                }
                            }
                        } else {
                            Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
                        }
                    }),
                'edit title'
            );
        }
    };

    titleEntered = (e: React.KeyboardEvent) => {
        if (e.key === 'Enter') {
            e.stopPropagation();
            (e.target as any).blur();
        }
    };

    @action onContainerDown = (e: React.PointerEvent): void => {
        const first = SelectionManager.Views()[0];
        const effectiveAcl = GetEffectiveAcl(first.rootDoc);
        console.log(effectiveAcl)
        if (effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment) {
            setupMoveUpEvents(
                this,
                e,
                e => this.onBackgroundMove(true, e),
                e => {},
                emptyFunction
            );
        }
    };

    @action onTitleDown = (e: React.PointerEvent): void => {
        const first = SelectionManager.Views()[0];
        const effectiveAcl = GetEffectiveAcl(first.rootDoc);
        if (effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment) {
            setupMoveUpEvents(
                this,
                e,
                e => this.onBackgroundMove(true, e),
                e => {},
                action(e => {
                    !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('#') ? this.selectionTitle : this._titleControlString);
                    this._editingTitle = true;
                    this._keyinput.current && setTimeout(this._keyinput.current.focus);
                })
            );
        }
    };

    onBackgroundDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, e => this.onBackgroundMove(false, e), emptyFunction, emptyFunction);

    @action
    onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
        const first = SelectionManager.Views()[0];
        const effectiveAcl = GetEffectiveAcl(first.rootDoc);
        if (effectiveAcl != AclAdmin && effectiveAcl != AclEdit && effectiveAcl != AclAugment){
            return false;
        }      
const dragDocView = SelectionManager.Views()[0];
        const containers = new Set<Doc | undefined>();
        SelectionManager.Views().forEach(v => containers.add(DocCast(v.rootDoc.embedContainer)));
        if (containers.size > 1) return false;
        const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
        const dragData = new DragManager.DocumentDragData(
            SelectionManager.Views().map(dv => dv.props.Document),
            dragDocView.props.dropAction
        );
        dragData.offset = dragDocView.props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
        dragData.moveDocument = dragDocView.props.moveDocument;
        dragData.removeDocument = dragDocView.props.removeDocument;
        dragData.isDocDecorationMove = true;
        dragData.canEmbed = dragTitle;
        this._hidden = true;
        DragManager.StartDocumentDrag(
            SelectionManager.Views().map(dv => dv.ContentDiv!),
            dragData,
            e.x,
            e.y,
            {
                dragComplete: action(e => {
                    dragData.canEmbed && SelectionManager.DeselectAll();
                    this._hidden = false;
                }),
                hideSource: true,
            }
        );
        return true;
    };

    _deleteAfterIconify = false;
    _iconifyBatch: UndoManager.Batch | undefined;
    onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
        const views = SelectionManager.Views()
            .slice()
            .filter(v => v && v.props.renderDepth > 0);
        if (forceDeleteOrIconify === false && this._iconifyBatch) return;
        this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false;
        var iconifyingCount = views.length;
        const finished = action((force?: boolean) => {
            if ((force || --iconifyingCount === 0) && this._iconifyBatch) {
                if (this._deleteAfterIconify) {
                    views.forEach(iconView => {
                        Doc.setNativeView(iconView.props.Document);
                        if (iconView.props.Document.activeFrame) {
                            iconView.props.Document.opacity = 0; // bcz: hacky ... allows inkMasks and other documents to be "turned off" without removing them from the animated collection which allows them to function properly in a presenation.
                        } else {
                            iconView.props.removeDocument?.(iconView.props.Document);
                        }
                    });
                    SelectionManager.DeselectAll();
                }
                this._iconifyBatch?.end();
                this._iconifyBatch = undefined;
            }
        });
        if (!this._iconifyBatch) {
            this._iconifyBatch = UndoManager.StartBatch(forceDeleteOrIconify ? 'delete selected docs' : 'iconifying');
        } else {
            forceDeleteOrIconify = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes
        }

        if (forceDeleteOrIconify) finished(forceDeleteOrIconify);
        else if (!this._deleteAfterIconify) views.forEach(dv => dv.iconify(finished));
    };
    onMaximizeDown = (e: React.PointerEvent) => {
        setupMoveUpEvents(
            this,
            e,
            () => {
                DragManager.StartWindowDrag?.(e, [SelectionManager.Views().slice(-1)[0].rootDoc]);
                return true;
            },
            emptyFunction,
            this.onMaximizeClick,
            false,
            false
        );
    };

    onMaximizeClick = (e: any): void => {
        const selectedDocs = SelectionManager.Views();
        if (selectedDocs.length) {
            if (e.ctrlKey) {
                // open an embedding in a new tab with Ctrl Key
                CollectionDockingView.AddSplit(Doc.BestEmbedding(selectedDocs[0].rootDoc), OpenWhereMod.right);
            } else if (e.shiftKey) {
                // open centered in a new workspace with Shift Key
                const embedding = Doc.MakeEmbedding(selectedDocs[0].rootDoc);
                embedding.embedContainer = undefined;
                embedding.x = -embedding[Width]() / 2;
                embedding.y = -embedding[Height]() / 2;
                CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([embedding], { title: 'Tab for ' + embedding.title }), OpenWhereMod.right);
            } else if (e.altKey) {
                // open same document in new tab
                CollectionDockingView.ToggleSplit(selectedDocs[0].rootDoc, OpenWhereMod.right);
            } else {
                var openDoc = selectedDocs[0].rootDoc;
                if (openDoc.layout_fieldKey === 'layout_icon') {
                    openDoc = DocListCast(openDoc.proto_embeddings).find(embedding => !embedding.embedContainer) ?? Doc.MakeEmbedding(openDoc);
                    Doc.deiconifyView(openDoc);
                }
                LightboxView.SetLightboxDoc(
                    openDoc,
                    undefined,
                    selectedDocs.slice(1).map(view => view.rootDoc)
                );
            }
        }
        SelectionManager.DeselectAll();
    };

    onIconifyClick = (): void => {
        SelectionManager.Views().forEach(dv => dv?.iconify());
        SelectionManager.DeselectAll();
    };

    onSelectorClick = () => SelectionManager.Views()?.[0]?.props.docViewPath?.().lastElement()?.select(false);
    /**
     * Handles setting up events when user clicks on the border radius editor
     * @param e PointerEvent
     */
    @action
    onRadiusDown = (e: React.PointerEvent): void => {
        this._isRounding = DocumentDecorations.Instance.Interacting = true;
        this._resizeUndo = UndoManager.StartBatch('DocDecs set radius');
        // Call util move event function
        setupMoveUpEvents(
            this, // target
            e, // pointerEvent
            (e, down) => {
                const x = this.Bounds.x + 3;
                const y = this.Bounds.y + 3;
                const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
                let dist = Math.sqrt((e.clientX - x) * (e.clientX - x) + (e.clientY - y) * (e.clientY - y));
                if (e.clientX < x && e.clientY < y) dist = 0;
                SelectionManager.Views()
                    .map(dv => dv.props.Document)
                    .map(doc => {
                        const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2);
                        const ratio = dist / maxDist;
                        const radius = Math.min(1, ratio) * docMax;
                        doc.layout_borderRounding = `${radius}px`;
                    });
                return false;
            }, // moveEvent
            action(e => {
                DocumentDecorations.Instance.Interacting = this._isRounding = false;
                this._resizeUndo?.end();
            }), // upEvent
            e => {}, // clickEvent,
            true
        );
    };

    @action
    onLockDown = (e: React.PointerEvent): void => {
        // Call util move event function
        setupMoveUpEvents(
            this, // target
            e, // pointerEvent
            returnFalse, // moveEvent
            emptyFunction, // upEvent
            e => {
                UndoManager.RunInBatch(
                    () =>
                        SelectionManager.Views().map(dv => {
                            dv.rootDoc._lockedPosition = !dv.rootDoc._lockedPosition;
                            dv.rootDoc._pointerEvents = dv.rootDoc._lockedPosition ? 'none' : undefined;
                        }),
                    'toggleBackground'
                );
            } // clickEvent
        );
    };

    setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => {
        const newloccentern = seldocview.props.ScreenToLocalTransform().transformPoint(rotCenter[0], rotCenter[1]);
        const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2];
        const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI);
        seldocview.rootDoc.rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width);
        seldocview.rootDoc.rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height);
    };

    @action
    onRotateCenterDown = (e: React.PointerEvent): void => {
        this._isRotating = true;
        const seldocview = SelectionManager.Views()[0];
        setupMoveUpEvents(
            this,
            e,
            action((e: PointerEvent, down: number[], delta: number[]) => {
                this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]);
                return false;
            }), // moveEvent
            action(action(() => (this._isRotating = false))), // upEvent
            action((e, doubleTap) => {
                if (doubleTap) {
                    seldocview.rootDoc.rotation_centerX = 0.5;
                    seldocview.rootDoc.rotation_centerY = 0.5;
                }
            })
        );
    };

    @action
    onRotateDown = (e: React.PointerEvent): void => {
        this._isRotating = true;
        const rcScreen = { X: this.rotCenter[0], Y: this.rotCenter[1] };
        const rotateUndo = UndoManager.StartBatch('drag rotation');
        const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke);
        const centerPoint = this.rotCenter.slice();
        const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>();
        const seldocview = SelectionManager.Views()[0];
        SelectionManager.Views().forEach(dv => {
            const accumRot = (NumCast(dv.rootDoc._rotation) / 180) * Math.PI;
            const localRotCtr = dv.props.ScreenToLocalTransform().transformPoint(rcScreen.X, rcScreen.Y);
            const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.rootDoc.width) / 2, localRotCtr[1] - NumCast(dv.rootDoc.height) / 2];
            const startRotCtr = Utils.rotPt(localRotCtrOffset[0], localRotCtrOffset[1], -accumRot);
            const unrotatedDocPos = { x: NumCast(dv.rootDoc.x) + localRotCtrOffset[0] - startRotCtr.x, y: NumCast(dv.rootDoc.y) + localRotCtrOffset[1] - startRotCtr.y };
            infos.set(dv.rootDoc, { unrotatedDocPos, startRotCtr, accumRot });
        });
        const infoRot = (angle: number, isAbs = false) => {
            SelectionManager.Views().forEach(
                action(dv => {
                    const { unrotatedDocPos, startRotCtr, accumRot } = infos.get(dv.rootDoc)!;
                    const endRotCtr = Utils.rotPt(startRotCtr.x, startRotCtr.y, isAbs ? angle : accumRot + angle);
                    infos.set(dv.rootDoc, { unrotatedDocPos, startRotCtr, accumRot: isAbs ? angle : accumRot + angle });
                    dv.rootDoc.x = infos.get(dv.rootDoc)!.unrotatedDocPos.x - (endRotCtr.x - startRotCtr.x);
                    dv.rootDoc.y = infos.get(dv.rootDoc)!.unrotatedDocPos.y - (endRotCtr.y - startRotCtr.y);
                    dv.rootDoc._rotation = ((isAbs ? 0 : NumCast(dv.rootDoc._rotation)) + (angle * 180) / Math.PI) % 360; // Rotation between -360 and 360
                })
            );
        };
        setupMoveUpEvents(
            this,
            e,
            (e: PointerEvent, down: number[], delta: number[]) => {
                const previousPoint = { X: e.clientX, Y: e.clientY };
                const movedPoint = { X: e.clientX - delta[0], Y: e.clientY - delta[1] };
                const deltaAng = InkStrokeProperties.angleChange(movedPoint, previousPoint, rcScreen);
                if (selectedInk.length) {
                    deltaAng && InkStrokeProperties.Instance.rotateInk(selectedInk, deltaAng, rcScreen);
                    this.setRotateCenter(seldocview, centerPoint);
                } else {
                    infoRot(deltaAng);
                }
                return false;
            }, // moveEvent
            action(() => {
                const oldRotation = NumCast(seldocview.rootDoc._rotation);
                const diff = oldRotation - Math.round(oldRotation / 45) * 45;
                if (Math.abs(diff) < 5) {
                    if (selectedInk.length) {
                        InkStrokeProperties.Instance.rotateInk(selectedInk, ((Math.round(oldRotation / 45) * 45 - oldRotation) / 180) * Math.PI, rcScreen);
                    } else {
                        infoRot(((Math.round(oldRotation / 45) * 45) / 180) * Math.PI, true);
                    }
                }
                if (selectedInk.length) {
                    this.setRotateCenter(seldocview, centerPoint);
                }
                this._isRotating = false;
                rotateUndo?.end();
            }), // upEvent
            action(e => (this._showRotCenter = !this._showRotCenter)) // clickEvent
        );
    };

    @action
    onPointerDown = (e: React.PointerEvent): void => {
        setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
        this.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
        this._resizeHdlId = e.currentTarget.className;
        const bounds = e.currentTarget.getBoundingClientRect();
        this._offX = this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX;
        this._offY = this._resizeHdlId.toLowerCase().includes('top') ? bounds.bottom - e.clientY : bounds.top - e.clientY;
        this._resizeUndo = UndoManager.StartBatch('drag resizing');
        this._snapX = e.pageX;
        this._snapY = e.pageY;
        const ffviewSet = new Set<CollectionFreeFormView>();
        SelectionManager.Views().forEach(docView => {
            const ffview = docView.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
            ffview && ffviewSet.add(ffview);
            this._dragHeights.set(docView.layoutDoc, { start: NumCast(docView.rootDoc._height), lowest: NumCast(docView.rootDoc._height) });
        });
        Array.from(ffviewSet).map(ffview => ffview.setupDragLines(false));
    };

    onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
        const first = SelectionManager.Views()[0];
        const effectiveAcl = GetEffectiveAcl(first.rootDoc);
        if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false;
        if (!first) return false;
        let thisPt = { x: e.clientX - this._offX, y: e.clientY - this._offY };
        var fixedAspect = Doc.NativeAspect(first.layoutDoc);

        const resizeHdl = this._resizeHdlId.split(' ')[0];
        if (fixedAspect && (resizeHdl === 'documentDecorations-bottomRightResizer' || resizeHdl === 'documentDecorations-topLeftResizer')) {
            // need to generalize for bl and tr drag handles
            const project = (p: number[], a: number[], b: number[]) => {
                const atob = [b[0] - a[0], b[1] - a[1]];
                const atop = [p[0] - a[0], p[1] - a[1]];
                const len = atob[0] * atob[0] + atob[1] * atob[1];
                let dot = atop[0] * atob[0] + atop[1] * atob[1];
                const t = dot / len;
                dot = (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0]);
                return [a[0] + atob[0] * t, a[1] + atob[1] * t];
            };
            const tl = first.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
            const drag = project([e.clientX + this._offX, e.clientY + this._offY], tl, [tl[0] + fixedAspect, tl[1] + 1]);
            thisPt = DragManager.snapDragAspect(drag, fixedAspect);
        } else {
            thisPt = DragManager.snapDrag(e, -this._offX, -this._offY, this._offX, this._offY);
        }

        move[0] = thisPt.x - this._snapX;
        move[1] = thisPt.y - this._snapY;
        this._snapX = thisPt.x;
        this._snapY = thisPt.y;
        let dragBottom = false,
            dragRight = false,
            dragBotRight = false,
            dragTop = false;
        let dXin = 0,
            dYin = 0,
            dWin = 0,
            dHin = 0;
        switch (this._resizeHdlId.split(' ')[0]) {
            case '':
                break;
            case 'documentDecorations-topLeftResizer':
                dXin = -1;
                dYin = -1;
                dWin = -move[0];
                dHin = -move[1];
                break;
            case 'documentDecorations-topRightResizer':
                dWin = move[0];
                dYin = -1;
                dHin = -move[1];
                break;
            case 'documentDecorations-topResizer':
                dYin = -1;
                dHin = -move[1];
                dragTop = true;
                break;
            case 'documentDecorations-bottomLeftResizer':
                dXin = -1;
                dWin = -move[0];
                dHin = move[1];
                break;
            case 'documentDecorations-bottomRightResizer':
                dWin = move[0];
                dHin = move[1];
                dragBotRight = true;
                break;
            case 'documentDecorations-bottomResizer':
                dHin = move[1];
                dragBottom = true;
                break;
            case 'documentDecorations-leftResizer':
                dXin = -1;
                dWin = -move[0];
                break;
            case 'documentDecorations-rightResizer':
                dWin = move[0];
                dragRight = true;
                break;
        }

        const isGroup = first.rootDoc._isGroup ? first.rootDoc : undefined;
        const scaleViews = isGroup ? DocListCast(isGroup.data).map(doc => DocumentManager.Instance.getFirstDocumentView(doc)!) : SelectionManager.Views();
        const aggBounds = aggregateBounds(scaleViews.map(view => view.rootDoc) as any, 0, 0);
        const refWidth = aggBounds.r - aggBounds.x;
        const refHeight = aggBounds.b - aggBounds.y;
        const scaleRefPt = first.props
            .ScreenToLocalTransform()
            .inverse()
            .transformPoint(
                NumCast(isGroup?._xPadding) + (dXin ? refWidth : 0), //
                NumCast(isGroup?._yPadding) + (dYin ? refHeight : 0)
            );
        scaleViews.forEach(
            action((docView: DocumentView) => {
                if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions();
                if (dXin !== 0 || dYin !== 0 || dWin !== 0 || dHin !== 0) {
                    const doc = docView.rootDoc;
                    const refCent = docView.props.ScreenToLocalTransform().transformPoint(scaleRefPt[0], scaleRefPt[1]);

                    if (doc.nativeHeightUnfrozen && !NumCast(doc.nativeHeight) && doc._nativeWidth !== undefined) {
                        doc._nativeHeight = (NumCast(doc._height) / NumCast(doc._width, 1)) * docView.nativeWidth;
                    }
                    const nwidth = docView.nativeWidth;
                    const nheight = docView.nativeHeight;
                    const docwidth = NumCast(doc._width);
                    let docheight = (hgt => (!hgt || isNaN(hgt) ? 20 : hgt))(NumCast(doc._height) || (nheight / nwidth) * docwidth);
                    let dW = docwidth * (dWin / refWidth);
                    let dH = docheight * (dHin / refHeight);
                    const scale = docView.props.ScreenToLocalTransform().Scale;
                    const modifyNativeDim = (e.ctrlKey && doc.nativeDimModifiable) || (doc.layout_forceReflow && !dragBottom && !dragTop) || (doc.nativeHeightUnfrozen && (dragBottom || dragTop || e.ctrlKey));
                    if (nwidth && nheight) {
                        if (nwidth / nheight !== docwidth / docheight && !dragBottom && !dragTop) {
                            docheight = (nheight / nwidth) * docwidth;
                        }
                        if (modifyNativeDim && !dragBottom && !dragTop) {
                            // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction
                            if (Math.abs(dW) > Math.abs(dH)) dH = (dW * nheight) / nwidth;
                            else dW = (dH * nwidth) / nheight;
                        }
                    }
                    let actualdW = Math.max(docwidth + dW * scale, 20);
                    let actualdH = Math.max(docheight + dH * scale, 20);
                    let dX = !dWin ? 0 : scale * refCent[0] * (1 - (1 + dWin / refWidth));
                    let dY = !dHin ? 0 : scale * refCent[1] * (1 - (1 + dHin / refHeight));
                    const preserveNativeDim = doc._nativeHeightUnfrozen === false && doc._nativeDimModifiable === false;
                    const fixedAspect = nwidth && nheight && (!doc._layout_fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable);
                    if (fixedAspect) {
                        if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop) || !modifyNativeDim)) || dragRight) {
                            if (dragRight && modifyNativeDim) {
                                if (Doc.NativeWidth(doc)) {
                                    doc._nativeWidth = (actualdW / (docwidth || 1)) * Doc.NativeWidth(doc);
                                }
                            } else {
                                if (!doc._layout_fitWidth || preserveNativeDim) {
                                    actualdH = (nheight / nwidth) * actualdW;
                                    doc._height = actualdH;
                                } else if (!modifyNativeDim || dragBotRight) {
                                    doc._height = actualdH;
                                }
                            }
                            doc._width = actualdW;
                        } else {
                            if ((dragBottom || dragTop) && (modifyNativeDim || (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._layout_fitWidth))) {
                                // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height.  But they are marked to allow their nativeHeight
                                // to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match
                                // a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used)
                                doc._nativeHeight = (actualdH / (docheight || 1)) * Doc.NativeHeight(doc);
                                doc._layout_autoHeight = false;
                            } else {
                                if (!doc._layout_fitWidth || preserveNativeDim) {
                                    actualdW = (nwidth / nheight) * actualdH;
                                    doc._width = actualdW;
                                } else if (!modifyNativeDim || dragBotRight) {
                                    doc._width = actualdW;
                                }
                            }
                            if (!modifyNativeDim) {
                                actualdH = (nheight / nwidth) * docwidth; //, actualdH);
                            }
                            doc._height = actualdH;
                        }
                    } else {
                        const rotCtr = [docwidth / 2, docheight / 2];
                        const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI);

                        const maxHeight = doc.nativeHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling();
                        dH && (doc._height = actualdH > maxHeight && maxHeight ? maxHeight : actualdH);
                        dW && (doc._width = actualdW);
                        dH && (doc._layout_autoHeight = false);

                        const rotCtr2 = [NumCast(doc._width) / 2, NumCast(doc._height) / 2];
                        const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._rotation) / 180) * Math.PI);
                        doc.x = NumCast(doc.x) + tlRotated.x + rotCtr[0] - (tlRotated2.x + rotCtr2[0]); // doc shifts by amount topleft moves because rotation is about center of doc
                        doc.y = NumCast(doc.y) + tlRotated.y + rotCtr[1] - (tlRotated2.y + rotCtr2[1]);
                    }
                    doc.x = NumCast(doc.x) + dX;
                    doc.y = NumCast(doc.y) + dY;
                    doc._layout_modificationDate = new DateField();
                }
                const val = this._dragHeights.get(docView.layoutDoc);
                if (val) this._dragHeights.set(docView.layoutDoc, { start: val.start, lowest: Math.min(val.lowest, NumCast(docView.layoutDoc._height)) });
            })
        );
        return false;
    };

    @action
    onPointerUp = (e: PointerEvent): void => {
        this._resizeHdlId = '';
        this.Interacting = false;
        this._resizeUndo?.end();
        SnappingManager.clearSnapLines();

        // detect layout_autoHeight gesture and apply
        SelectionManager.Views()
            .map(docView => ({ doc: docView.layoutDoc, hgts: this._dragHeights.get(docView.layoutDoc) }))
            .filter(pair => pair.hgts && pair.hgts.lowest < pair.hgts.start && pair.hgts.lowest <= 20)
            .forEach(pair => (pair.doc._layout_autoHeight = true));
        //need to change points for resize, or else rotation/control points will fail.
        this._inkDragDocs
            .map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
            .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
                Doc.GetProto(doc).data = new InkField(
                    inkPts.map(
                        (
                            ipt // (new x — oldx) + newWidth * (oldxpoint /oldWidth)
                        ) => ({
                            X: NumCast(doc.x) - x + (NumCast(doc.width) * ipt.X) / width,
                            Y: NumCast(doc.y) - y + (NumCast(doc.height) * ipt.Y) / height,
                        })
                    )
                );
                Doc.SetNativeWidth(doc, undefined);
                Doc.SetNativeHeight(doc, undefined);
            });
    };

    @computed
    get selectionTitle(): string {
        if (SelectionManager.Views().length === 1) {
            const selected = SelectionManager.Views()[0];
            if (selected.ComponentView?.getTitle?.()) {
                return selected.ComponentView.getTitle();
            }
            if (this._titleControlString.startsWith('=')) {
                return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.rootDoc, this: selected.layoutDoc }, console.log).result?.toString() || '';
            }
            if (this._titleControlString.startsWith('#')) {
                return Field.toString(selected.props.Document[this._titleControlString.substring(1)] as Field) || '-unset-';
            }
            return this._accumulatedTitle;
        }
        return SelectionManager.Views().length > 1 ? '-multiple-' : '-unset-';
    }

    @computed get hasIcons() {
        return SelectionManager.Views().some(docView => docView.rootDoc.layout_fieldKey === 'layout_icon');
    }

    @observable _showRotCenter = false;
    @observable _rotCenter = [0, 0];
    @computed get rotCenter() {
        if (SelectionManager.Views().length) {
            const seldocview = SelectionManager.Views()[0];
            const loccenter = Utils.rotPt(
                NumCast(seldocview.rootDoc.rotation_centerX) * NumCast(seldocview.layoutDoc._width),
                NumCast(seldocview.rootDoc.rotation_centerY) * NumCast(seldocview.layoutDoc._height),
                (NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI
            );
            return seldocview.props
                .ScreenToLocalTransform()
                .inverse()
                .transformPoint(loccenter.x + NumCast(seldocview.layoutDoc._width) / 2, loccenter.y + NumCast(seldocview.layoutDoc._height) / 2);
        }
        return this._rotCenter;
    }

    @observable _showNothing = true;

    render() {
        const { b, r, x, y } = this.Bounds;
        const bounds = { b, r, x, y };
        const seldocview = SelectionManager.Views().lastElement();
        if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
            setTimeout(action(() => (this._showNothing = true)));
            return null;
        }

        // sharing
        // const docShareMode = Doc.GetProto(seldocview.rootDoc)['acl-Public'];
        const docShareMode = Doc.GetProto(seldocview.rootDoc)['acl-'+normalizeEmail(Doc.CurrentUserEmail)];
        const shareMode = StrCast(docShareMode);
        var shareSymbolIcon = null;
        switch (shareMode) {
            case 'Admin':
                shareSymbolIcon = '⬢ ';
                break;
            case 'Edit':
                shareSymbolIcon = '⬢ ';
                break;
            case 'Augment':
                shareSymbolIcon = '⬟ ';
                break;
            case 'View':
                shareSymbolIcon = '♦ ';
                break;
            case 'Not-Shared':
                shareSymbolIcon = '▲ ';
                break;
            default:
                shareSymbolIcon = '';
                break;
        }

        // hide the decorations if the parent chooses to hide it or if the document itself hides it
        const hideDecorations = seldocview.props.hideDecorations || seldocview.rootDoc.hideDecorations;
        const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.layout_hideResizeHandles || this._isRounding || this._isRotating;
        const hideTitle = hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.layout_hideDecorationTitle || this._isRounding || this._isRotating;
        const hideDocumentButtonBar = hideDecorations || seldocview.props.hideDocumentButtonBar || seldocview.rootDoc.layout_hideDocumentButtonBar || this._isRounding || this._isRotating;
        // if multiple documents have been opened at the same time, then don't show open button
        const hideOpenButton =
            hideDecorations ||
            seldocview.props.hideOpenButton ||
            seldocview.rootDoc.layout_hideOpenButton ||
            SelectionManager.Views().some(docView => docView.rootDoc._stayInCollection || docView.rootDoc.isGroup || docView.rootDoc.layout_hideOpenButton) ||
            this._isRounding ||
            this._isRotating;
        const hideDeleteButton =
            hideDecorations ||
            this._isRounding ||
            this._isRotating ||
            seldocview.props.hideDeleteButton ||
            seldocview.rootDoc.hideDeleteButton ||
            SelectionManager.Views().some(docView => {
                const collectionAcl = docView.props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView.props.docViewPath().lastElement().rootDoc[DocData]) : AclEdit;
                return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin);
            });
        const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => (
            <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top">
                <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => click!(e)))}>
                    <FontAwesomeIcon icon={icon as any} />
                </div>
            </Tooltip>
        );

        const colorScheme = StrCast(Doc.ActiveDashboard?.colorScheme);

        const leftBounds = this.props.boundsLeft;
        const topBounds = LightboxView.LightboxDoc ? 0 : this.props.boundsTop;
        bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
        bounds.y = Math.max(topBounds, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
        const borderRadiusDraggerWidth = 15;
        bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth));
        bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight));

        const useLock = bounds.r - bounds.x > 135 && seldocview.props.CollectionFreeFormDocumentView;
        const useRotation = !hideResizers && seldocview.rootDoc.type !== DocumentType.EQUATION && seldocview.props.CollectionFreeFormDocumentView; // when do we want an object to not rotate?
        const rotation = SelectionManager.Views().length == 1 ? NumCast(seldocview.rootDoc._rotation) : 0;

        const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : '';

        // Radius constants
        const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
        const borderRadius = numberValue(StrCast(seldocview.rootDoc.borderRounding));
        const docMax = Math.min(NumCast(seldocview.rootDoc.width) / 2, NumCast(seldocview.rootDoc.height) / 2);
        const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
        const radiusHandle = (borderRadius / docMax) * maxDist;
        const radiusHandleLocation = Math.min(radiusHandle, maxDist);

        const titleArea = this._editingTitle ? (
            <input
                ref={this._keyinput}
                className={`documentDecorations-title${colorScheme}`}
                type="text"
                name="dynbox"
                autoComplete="on"
                value={hideTitle ? '' : this._accumulatedTitle}
                onBlur={e => !hideTitle && this.titleBlur()}
                onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))}
                onKeyDown={hideTitle ? emptyFunction : this.titleEntered}
                onPointerDown={e => e.stopPropagation()}
            />
        ) : (
            <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown}>
                <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${hideTitle ? '' : this.selectionTitle}`}</span>
            </div>
        );
        
        const sharingMenu = docShareMode ? (
            <div className='documentDecorations-share' onPointerDown={e => setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), e => {}, action(e => {}))} >
                <div className={`documentDecorations-share${shareMode}`}>
                    <span>{shareSymbolIcon + ' ' + shareMode}</span>
                </div>
            </div>
        ) : (
            <div />
        );
        return (
            <div className={`documentDecorations${colorScheme}`} style={{ opacity: this._showNothing ? 0.1 : undefined }}>
                <div
                    className="documentDecorations-background"
                    style={{
                        width: bounds.r - bounds.x + this._resizeBorderWidth + 'px',
                        height: bounds.b - bounds.y + this._resizeBorderWidth + 'px',
                        left: bounds.x - this._resizeBorderWidth / 2,
                        top: bounds.y - this._resizeBorderWidth / 2,
                        pointerEvents: DocumentDecorations.Instance.AddToSelection || this.Interacting ? 'none' : 'all',
                        display: SelectionManager.Views().length <= 1 || hideDecorations ? 'none' : undefined,
                    }}
                    onPointerDown={this.onBackgroundDown}
                    onContextMenu={e => {
                        e.preventDefault();
                        e.stopPropagation();
                    }}
                />
                {bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? null : (
                    <div>
                        <div
                            className="documentDecorations-container"
                            key="container"
                            style={{
                                transform: `translate(${bounds.x - this._resizeBorderWidth / 2}px, ${bounds.y - this._resizeBorderWidth / 2 - this._titleHeight}px) rotate(${rotation}deg)`,
                                transformOrigin: `50% calc(50% + 10px)`,
                                width: bounds.r - bounds.x + this._resizeBorderWidth + 'px',
                                height: bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight + 'px',
                            }}>
                            <div className="documentDecorations-topbar" style={{ display: hideDeleteButton && hideTitle && hideOpenButton ? 'none' : undefined }} onPointerDown={this.onContainerDown}>
                                {hideDeleteButton ? null : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
                                {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
                                {hideTitle ? null : titleArea}
                                {sharingMenu}
                                {hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')}
                            </div>
                            {hideResizers ? null : (
                                <>
                                    <div key="tl" className={`documentDecorations-topLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="t" className={`documentDecorations-topResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="tr" className={`documentDecorations-topRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="l" className={`documentDecorations-leftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="c" className={`documentDecorations-centerCont ${resizerScheme}`}></div>
                                    <div key="r" className={`documentDecorations-rightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="bl" className={`documentDecorations-bottomLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="b" className={`documentDecorations-bottomResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
                                    <div key="br" className={`documentDecorations-bottomRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />

                                    {seldocview.props.renderDepth <= 1 || !seldocview.props.docViewPath().lastElement() ? null : topBtn('selector', 'arrow-alt-circle-up', undefined, this.onSelectorClick, 'tap to select containing document')}
                                </>
                            )}
                            {useRounding && (
                                <div
                                    key="rad"
                                    style={{
                                        background: `${this._isRounding ? Colors.MEDIUM_BLUE : undefined}`,
                                        transform: `translate(${radiusHandleLocation}px, ${radiusHandleLocation}px)`,
                                    }}
                                    className={`documentDecorations-borderRadius`}
                                    onPointerDown={this.onRadiusDown}
                                    onContextMenu={e => e.preventDefault()}
                                />
                            )}

                            {hideDocumentButtonBar ? null : (
                                <div
                                    className="link-button-container"
                                    key="links"
                                    style={{
                                        transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
                                    }}>
                                    <DocumentButtonBar views={SelectionManager.Views} />
                                </div>
                            )}
                        </div>

                        {useRotation && (
                            <>
                                <div
                                    style={{
                                        position: 'absolute',
                                        transform: `rotate(${rotation}deg)`,
                                        width: this.Bounds.r - this.Bounds.x + 'px',
                                        height: this.Bounds.b - this.Bounds.y + 'px',
                                        left: this.Bounds.x,
                                        top: this.Bounds.y,
                                        pointerEvents: 'none',
                                    }}>
                                    {this._isRotating ? null : (
                                        <Tooltip enterDelay={750} title={<div className="dash-tooltip">tap to set rotate center, drag to rotate</div>}>
                                            <div className="documentDecorations-rotation" style={{ pointerEvents: 'all' }} onPointerDown={this.onRotateDown} onContextMenu={e => e.preventDefault()}>
                                                <IconButton icon={<FaUndo />} color={Colors.LIGHT_GRAY} />
                                            </div>
                                        </Tooltip>
                                    )}
                                </div>
                                {!this._showRotCenter ? null : (
                                    <div
                                        className="documentDecorations-rotationCenter"
                                        style={{ transform: `translate(${this.rotCenter[0] - 3}px, ${this.rotCenter[1] - 3}px)` }}
                                        onPointerDown={this.onRotateCenterDown}
                                        onContextMenu={e => e.preventDefault()}
                                    />
                                )}
                            </>
                        )}
                    </div>
                )}
            </div>
        );
    }
}
