import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Colors } from 'browndash-components';
import { concat, intersection } from 'lodash';
import { action, computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import Select from 'react-select';
import * as RequestPromise from 'request-promise';
import { Doc, DocListCast, DocListCastAsync, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc';
import { AclAdmin, AclPrivate, DocAcl, DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { StrCast } from '../../fields/Types';
import { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from '../../fields/util';
import { Utils } from '../../Utils';
import { DocServer } from '../DocServer';
import { DictationOverlay } from '../views/DictationOverlay';
import { MainViewModal } from '../views/MainViewModal';
import { DocumentView } from '../views/nodes/DocumentView';
import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
import { SearchBox } from '../views/search/SearchBox';
import { DocumentManager } from './DocumentManager';
import { GroupManager, UserOptions } from './GroupManager';
import { GroupMemberView } from './GroupMemberView';
import { SelectionManager } from './SelectionManager';
import './SharingManager.scss';
import { undoable } from './UndoManager';

export interface User {
    email: string;
    sharingDocumentId: string;
    linkDatabaseId: string;
}

/**
 * Interface for grouped options for the react-select component.
 */
interface GroupedOptions {
    label: string;
    options: UserOptions[];
}

// const SharingKey = "sharingPermissions";
// const PublicKey = "all";
// const DefaultColor = "black";

// used to differentiate between individuals and groups when sharing
const indType = '!indType/';
const groupType = '!groupType/';

const storage = 'data';

/**
 * A user who also has a sharing doc.
 */
interface ValidatedUser {
    user: User; // database minimal info to identify / communicate with a user (email, sharing doc id)
    sharingDoc: Doc; // document to share/message another user
    linkDatabase: Doc;
    userColor: string; // stored on the sharinDoc, extracted for convenience?
}

@observer
export class SharingManager extends React.Component<{}> {
    public static Instance: SharingManager;
    @observable private isOpen = false; // whether the SharingManager modal is open or not
    @observable public users: ValidatedUser[] = []; // the list of users with sharing docs
    @observable private targetDoc: Doc | undefined; // the document being shared
    @observable private targetDocView: DocumentView | undefined; // the DocumentView of the document being shared
    // @observable private copied = false;
    @observable private dialogueBoxOpacity = 1; // for the modal
    @observable private overlayOpacity = 0.4; // for the modal
    @observable private selectedUsers: UserOptions[] | null = null; // users (individuals/groups) selected to share with
    @observable private permissions: SharingPermissions = SharingPermissions.Edit; // the permission with which to share with other users
    @observable private individualSort: 'ascending' | 'descending' | 'none' = 'none'; // sorting options for the list of individuals
    @observable private groupSort: 'ascending' | 'descending' | 'none' = 'none'; // sorting options for the list of groups
    private shareDocumentButtonRef: React.RefObject<HTMLButtonElement> = React.createRef(); // ref for the share button, used for the position of the popup
    // if both showUserOptions and showGroupOptions are false then both are displayed
    @observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component)
    @observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component)
    private populating: boolean = false; // whether the list of users is populating or not
    @observable private overrideNested: boolean = false; // whether child docs in a collection/dashboard should be changed to be less private - initially selected so default is override
    @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used
    @observable private myDocAcls: boolean = false; // whether the My Docs checkbox is selected or not
    @observable private _buttonDown = false;

    // private get linkVisible() {
    //     return this.targetDoc ? this.targetDoc["acl-" + PublicKey] !== SharingPermissions.None : false;
    // }

    public open = (target?: DocumentView, target_doc?: Doc) => {
        this.populateUsers();
        runInAction(() => {
            this.targetDocView = target;
            this.targetDoc = target_doc || target?.props.Document;
            DictationOverlay.Instance.hasActiveModal = true;
            this.isOpen = this.targetDoc !== undefined;
            this.permissions = SharingPermissions.Augment;
            this.overrideNested = true;
        });
    };

    public close = action(() => {
        this.isOpen = false;
        this.selectedUsers = null; // resets the list of users and selected users (in the react-select component)
        TaskCompletionBox.taskCompleted = false;
        setTimeout(
            action(() => {
                // this.copied = false;
                DictationOverlay.Instance.hasActiveModal = false;
                this.targetDoc = undefined;
            }),
            500
        );
        this.layoutDocAcls = false;
    });

    constructor(props: {}) {
        super(props);
        SharingManager.Instance = this;
    }

    /**
     * Populates the list of users.
     */
    componentDidMount() {
        this.populateUsers();
    }

    /**
     * Populates the list of validated users (this.users) by adding registered users which have a sharingDocument.
     */
    populateUsers = async () => {
        if (!this.populating && Doc.UserDoc()[Id] !== '__guest__') {
            this.populating = true;
            const userList = await RequestPromise.get(Utils.prepend('/getUsers'));
            const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== Doc.CurrentUserEmail);
            const docs = await DocServer.GetRefFields(raw.reduce((list, user) => [...list, user.sharingDocumentId, user.linkDatabaseId], [] as string[]));
            raw.map(
                action((newUser: User) => {
                    const sharingDoc = docs[newUser.sharingDocumentId];
                    const linkDatabase = docs[newUser.linkDatabaseId];
                    if (sharingDoc instanceof Doc && linkDatabase instanceof Doc) {
                        if (!this.users.find(user => user.user.email === newUser.email)) {
                            this.users.push({ user: newUser, sharingDoc, linkDatabase, userColor: StrCast(sharingDoc.userColor) });
                            // LinkManager.addLinkDB(sharer.linkDatabase);
                        }
                    }
                })
            );
            this.populating = false;
        }
    };

    /**
     * Shares the document with a user.
     */
    setInternalSharing = undoable((recipient: ValidatedUser, permission: string, targetDoc: Doc | undefined) => {
        const { user, sharingDoc } = recipient;
        const target = targetDoc || this.targetDoc!;
        const acl = `acl-${normalizeEmail(user.email)}`;
        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
        docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => {
            distributeAcls(acl, permission as SharingPermissions, doc);
            if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc);
            else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc);
        });
    }, 'set Doc permissions');

    /**
     * Sets the permission on the target for the group.
     * @param group
     * @param permission
     */
    setInternalGroupSharing = undoable((group: Doc | { title: string }, permission: string, targetDoc?: Doc) => {
        const target = targetDoc || this.targetDoc!;
        const acl = `acl-${normalizeEmail(StrCast(group.title))}`;

        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
        docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => {
            distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.overrideNested);

            if (group instanceof Doc) {
                Doc.AddDocToList(group, 'docsShared', doc);

                this.users
                    .filter(({ user: { email } }) => JSON.parse(StrCast(group.members)).includes(email))
                    .forEach(({ user, sharingDoc }) => {
                        if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc); // add the doc to the sharingDoc if it hasn't already been added
                        else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); // remove the doc from the list if it already exists
                    });
            }
        });
    }, 'set group permissions');

    /**
     * Shares the documents shared with a group with a new user who has been added to that group.
     * @param group
     * @param emailId
     */
    shareWithAddedMember = (group: Doc, emailId: string, retry: boolean = true) => {
        const user = this.users.find(({ user: { email } }) => email === emailId)!;
        const self = this;
        if (group.docsShared) {
            if (!user) retry && this.populateUsers().then(() => self.shareWithAddedMember(group, emailId, false));
            else {
                DocListCastAsync(user.sharingDoc[storage]).then(userdocs =>
                    DocListCastAsync(group.docsShared).then(dl => {
                        const filtered = dl?.filter(doc => !userdocs?.includes(doc));
                        filtered && userdocs?.push(...filtered);
                    })
                );
            }
        }
    };

    /**
     * Called from the properties sidebar to change permissions of a user.
     */
    shareFromPropertiesSidebar = undoable((shareWith: string, permission: SharingPermissions, docs: Doc[], layout: boolean) => {
        if (layout) this.layoutDocAcls = true;
        if (shareWith !== 'Public' && shareWith !== 'Override') {
            const user = this.users.find(({ user: { email } }) => email === (shareWith === 'Me' ? Doc.CurrentUserEmail : shareWith));
            docs.forEach(doc => {
                if (user) this.setInternalSharing(user, permission, doc);
                else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, doc, undefined, true);
            });
        } else {
            docs.forEach(doc => {
                if (GetEffectiveAcl(doc) === AclAdmin) {
                    distributeAcls(`acl-${shareWith}`, permission, doc, undefined, true);
                }
            });
        }
        this.layoutDocAcls = false;
    }, 'sidebar set permissions');

    /**
     * Removes the documents shared with a user through a group when the user is removed from the group.
     * @param group
     * @param emailId
     */
    removeMember = (group: Doc, emailId: string) => {
        const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!;

        if (group.docsShared) {
            DocListCastAsync(user.sharingDoc[storage]).then(userdocs =>
                DocListCastAsync(group.docsShared).then(dl => {
                    const remaining = userdocs?.filter(doc => !dl?.includes(doc)) || [];
                    userdocs?.splice(0, userdocs.length, ...remaining);
                })
            );
        }
    };

    /**
     * Removes a group's permissions from documents that have been shared with it.
     * @param group
     */
    removeGroup = (group: Doc) => {
        if (group.docsShared) {
            DocListCast(group.docsShared).forEach(doc => {
                const acl = `acl-${StrCast(group.title)}`;
                distributeAcls(acl, SharingPermissions.None, doc);

                const members: string[] = JSON.parse(StrCast(group.members));
                const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));

                users.forEach(({ sharingDoc }) => Doc.RemoveDocFromList(sharingDoc, storage, doc));
            });
        }
    };

    // private setExternalSharing = (permission: string) => {
    //     const targetDoc = this.targetDoc;
    //     if (!targetDoc) {
    //         return;
    //     }
    //     targetDoc["acl-" + PublicKey] = permission;
    // }s

    /**
     * Copies the Public sharing url to the user's clipboard.
     */
    private copyURL = (e: any) => {
        Utils.CopyText(Utils.shareUrl(this.targetDoc![Id]));
    };

    /**
     * Returns the SharingPermissions (Admin, Can Edit etc) access that's used to share
     */
    private sharingOptions(uniform: boolean, override?: boolean) {
        const dropdownValues: string[] = Object.values(SharingPermissions);
        if (!uniform) dropdownValues.unshift('-multiple-');
        if (!override) dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1);
        return dropdownValues.map(permission => (
            <option key={permission} value={permission}>
                {concat(ReverseHierarchyMap.get(permission)?.image, ' ', permission)}
            </option>
        ));
    }

    private focusOn = (contents: string) => {
        const title = this.targetDoc ? StrCast(this.targetDoc.title) : '';
        const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc];
        return (
            <span
                className="focus-span"
                title={title}
                onClick={() => {
                    if (this.targetDoc && this.targetDocView && docs.length === 1) {
                        DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true });
                    }
                }}
                onPointerEnter={action(() => {
                    if (docs.length) {
                        docs.forEach(doc => doc && Doc.BrushDoc(doc));
                        this.dialogueBoxOpacity = 0.1;
                        this.overlayOpacity = 0.1;
                    }
                })}
                onPointerLeave={action(() => {
                    if (docs.length) {
                        docs.forEach(doc => doc && Doc.UnBrushDoc(doc));
                        this.dialogueBoxOpacity = 1;
                        this.overlayOpacity = 0.4;
                    }
                })}>
                {contents}
            </span>
        );
    };

    /**
     * Handles changes in the users selected in react-select
     */
    @action
    handleUsersChange = (selectedOptions: any) => {
        this.selectedUsers = selectedOptions as UserOptions[];
    };

    /**
     * Handles changes in the permission chosen to share with someone with
     */
    handlePermissionsChange = undoable(
        action((event: React.ChangeEvent<HTMLSelectElement>) => {
            this.permissions = event.currentTarget.value as SharingPermissions;
        }),
        'permission change'
    );

    /**
     * Calls the relevant method for sharing, displays the popup, and resets the relevant variables.
     */
    share = undoable(
        action(() => {
            if (this.selectedUsers) {
                this.selectedUsers.forEach(user => {
                    if (user.value.includes(indType)) {
                        this.setInternalSharing(this.users.find(u => u.user.email === user.label)!, this.permissions, undefined);
                    } else {
                        this.setInternalGroupSharing(GroupManager.Instance.getGroup(user.label)!, this.permissions);
                    }
                });

                const { left, width, top, height } = this.shareDocumentButtonRef.current!.getBoundingClientRect();
                TaskCompletionBox.popupX = left - 1.5 * width;
                TaskCompletionBox.popupY = top - 1.5 * height;
                TaskCompletionBox.textDisplayed = 'Document shared!';
                TaskCompletionBox.taskCompleted = true;
                setTimeout(
                    action(() => (TaskCompletionBox.taskCompleted = false)),
                    2000
                );

                this.layoutDocAcls = false;
                this.selectedUsers = null;
            }
        }),
        'share Doc'
    );

    /**
     * Sorting algorithm to sort users.
     */
    sortUsers = (u1: ValidatedUser, u2: ValidatedUser) => {
        const { email: e1 } = u1.user;
        const { email: e2 } = u2.user;
        return e1 < e2 ? -1 : e1 === e2 ? 0 : 1;
    };

    /**
     * Sorting algorithm to sort groups.
     */
    sortGroups = (group1: Doc, group2: Doc) => {
        const g1 = StrCast(group1.title);
        const g2 = StrCast(group2.title);
        return g1 < g2 ? -1 : g1 === g2 ? 0 : 1;
    };

    /**
     * @returns the main interface of the SharingManager.
     */
    @computed get sharingInterface() {
        if (!this.targetDoc) return null;
        TraceMobx();
        const groupList = GroupManager.Instance?.allGroups || [];

        const sortedUsers = this.users
            .slice()
            .sort(this.sortUsers)
            .map(({ user: { email } }) => ({ label: email, value: indType + email }));
        const sortedGroups = groupList
            .slice()
            .sort(this.sortGroups)
            .map(({ title }) => ({ label: StrCast(title), value: groupType + StrCast(title) }));

        // the next block handles the users shown (individuals/groups/both)
        const options: GroupedOptions[] = [];
        if (GroupManager.Instance) {
            if ((this.showUserOptions && this.showGroupOptions) || (!this.showUserOptions && !this.showGroupOptions)) {
                options.push({ label: 'Individuals', options: sortedUsers }, { label: 'Groups', options: sortedGroups });
            } else if (this.showUserOptions) options.push({ label: 'Individuals', options: sortedUsers });
            else options.push({ label: 'Groups', options: sortedGroups });
        }

        const users = this.individualSort === 'ascending' ? this.users.slice().sort(this.sortUsers) : this.individualSort === 'descending' ? this.users.slice().sort(this.sortUsers).reverse() : this.users;
        const groups = this.groupSort === 'ascending' ? groupList.slice().sort(this.sortGroups) : this.groupSort === 'descending' ? groupList.slice().sort(this.sortGroups).reverse() : groupList;

        let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.rootDoc);

        if (this.myDocAcls) {
            const newDocs: Doc[] = [];
            SearchBox.foreachRecursiveDoc(docs, (depth, doc) => newDocs.push(doc));
            docs = newDocs.filter(doc => GetEffectiveAcl(doc) === AclAdmin);
        }

        const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData];

        // tslint:disable-next-line: no-unnecessary-callback-wrapper
        const effectiveAcls = docs.map(doc => GetEffectiveAcl(doc));
        const admin = this.myDocAcls ? Boolean(docs.length) : effectiveAcls.every(acl => acl === AclAdmin);

        // users in common between all docs
        const commonKeys = intersection(docs).reduce((list, doc) => (doc?.[DocAcl] ? [...list, ...Object.keys(doc[DocAcl])] : list), [] as string[]);

        // the list of users shared with
        const userListContents = users
            // .filter(({ user }) => (docs.length > 1 ? commonKeys.includes(`acl-${normalizeEmail(user.email)}`) : docs[0]?.author !== user.email))
            .filter(({ user }) => docs[0]?.author !== user.email)
            .map(({ user, linkDatabase, sharingDoc, userColor }) => {
                const userKey = `acl-${normalizeEmail(user.email)}`;
                const uniform = docs.every(doc => doc?.[DocAcl]?.[userKey] === docs[0]?.[DocAcl]?.[userKey]);
                // const permissions = uniform ? StrCast(targetDoc?.[userKey]) : '-multiple-';
                let permissions = targetDoc[DocAcl][userKey] ? HierarchyMapping.get(targetDoc[DocAcl][userKey])?.name : StrCast(targetDoc[userKey]);
                permissions = uniform ? StrCast(targetDoc?.[userKey]) : '-multiple-';

                return !permissions ? null : (
                    <div key={userKey} className={'container'}>
                        <span className={'padding'}>{user.email}</span>
                        <div className="edit-actions">
                            {admin || this.myDocAcls ? (
                                <select className={`permissions-dropdown-${permissions}`} value={permissions} onChange={e => this.setInternalSharing({ user, linkDatabase, sharingDoc, userColor }, e.currentTarget.value, undefined)}>
                                    {this.sharingOptions(uniform)}
                                </select>
                            ) : (
                                <div className={`permissions-dropdown-${permissions}`}>
                                    {concat(ReverseHierarchyMap.get(permissions)?.image, ' ', permissions)}
                                    &nbsp;
                                </div>
                            )}
                        </div>
                    </div>
                );
            });

        // checks if every doc has the same author
        const sameAuthor = docs.every(doc => doc?.author === docs[0]?.author);

        // the owner of the doc and the current user are placed at the top of the user list.
        const userKey = `acl-${normalizeEmail(Doc.CurrentUserEmail)}`;
        const curUserPermission = StrCast(targetDoc[userKey]);
        // const curUserPermission = HierarchyMapping.get(effectiveAcls[0])!.name
        userListContents.unshift(
            sameAuthor ? (
                <div key={'owner'} className={'container'}>
                    <span className="padding">{targetDoc?.author === Doc.CurrentUserEmail ? 'Me' : StrCast(targetDoc?.author)}</span>
                    <div className="edit-actions">
                        <div className={'permissions-dropdown'}>Owner</div>
                    </div>
                </div>
            ) : null,
            sameAuthor && targetDoc?.author !== Doc.CurrentUserEmail ? (
                <div key={'me'} className={'container'}>
                    <span className={'padding'}>Me</span>
                    <div className="edit-actions">
                        <div className={`permissions-dropdown-${curUserPermission}`}>
                            {effectiveAcls.every(acl => acl === effectiveAcls[0]) ? concat(ReverseHierarchyMap.get(curUserPermission!)?.image, ' ', curUserPermission) : '-multiple-'}
                            &nbsp;
                        </div>
                    </div>
                </div>
            ) : null
        );

        // the list of groups shared with
        const groupListMap: (Doc | { title: string })[] = groups.filter(({ title }) => (docs.length > 1 ? commonKeys.includes(`acl-${normalizeEmail(StrCast(title))}`) : true));
        groupListMap.unshift({ title: 'Public' }); //, { title: "ALL" });
        const groupListContents = groupListMap.map(group => {
            let groupKey = `acl-${StrCast(group.title)}`;
            const uniform = docs.every(doc => doc?.[DocAcl]?.[groupKey] === docs[0]?.[DocAcl]?.[groupKey]);
            const permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-';

            return !permissions ? null : (
                <div key={groupKey} className={'container'}>
                    <div className={'padding'}>{StrCast(group.title)}</div>
                    &nbsp;
                    {group instanceof Doc ? (
                        <div className="group-info" onClick={action(() => (GroupManager.Instance.currentGroup = group))}>
                            <FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} />
                        </div>
                    ) : null}
                    <div className={'edit-actions'}>
                        {admin || this.myDocAcls ? (
                            <select className={`permissions-dropdown-${permissions}`} value={permissions} onChange={e => this.setInternalGroupSharing(group, e.currentTarget.value)}>
                                {this.sharingOptions(uniform, group.title === 'Override')}
                            </select>
                        ) : (
                            <div className={`permissions-dropdown-${permissions}`}>
                                {concat(ReverseHierarchyMap.get(permissions)?.image, ' ', permissions)}
                                &nbsp;
                            </div>
                        )}
                    </div>
                </div>
            );
        });
        return (
            <div className="sharing-interface">
                {GroupManager.Instance?.currentGroup ? <GroupMemberView group={GroupManager.Instance.currentGroup} onCloseButtonClick={action(() => (GroupManager.Instance.currentGroup = undefined))} /> : null}
                <div className="sharing-contents">
                    <p className="share-title">
                        <div className="share-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties/sharing-and-permissions/', '_blank')}>
                            <FontAwesomeIcon icon={'question-circle'} size={'sm'} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties/sharing-and-permissions/', '_blank')} />
                        </div>
                        <b>Share </b>
                        {this.focusOn(docs.length < 2 ? StrCast(targetDoc?.title, 'this document') : '-multiple-')}
                    </p>
                    <button
                        className="share-copy-link"
                        style={{ background: this._buttonDown ? Colors.LIGHT_BLUE : undefined }}
                        onPointerDown={action(e => (this._buttonDown = true))}
                        onPointerUp={action(e => (this._buttonDown = false))}
                        onClick={this.copyURL}>
                        <FontAwesomeIcon title="Copy Public URL" icon="copy" size="sm" />
                        &nbsp; Copy Public URL
                    </button>
                    <div className="close-button" onClick={this.close}>
                        <FontAwesomeIcon icon="times" color="black" size="lg" />
                    </div>
                    {admin ? (
                        <div className="share-container">
                            <div className="share-setup">
                                <Select
                                    className="user-search"
                                    placeholder="Enter user or group name..."
                                    isMulti
                                    isSearchable
                                    closeMenuOnSelect={false}
                                    options={options}
                                    onKeyDown={e => e.stopPropagation()}
                                    onChange={this.handleUsersChange}
                                    value={this.selectedUsers}
                                    styles={{
                                        indicatorSeparator: () => ({
                                            visibility: 'hidden',
                                        }),
                                    }}
                                />
                                <div className="permissions-select">
                                    <select className={`permissions-dropdown-${this.permissions}`} onChange={this.handlePermissionsChange} value={this.permissions}>
                                        {this.sharingOptions(true)}
                                    </select>
                                </div>
                                <button ref={this.shareDocumentButtonRef} className="share-button" onClick={this.share}>
                                    Share
                                </button>
                            </div>
                            <div className="sort-checkboxes">
                                <input type="checkbox" onChange={action(() => (this.showUserOptions = !this.showUserOptions))} /> <label style={{ marginRight: 10 }}>Individuals</label>
                                <input type="checkbox" onChange={action(() => (this.showGroupOptions = !this.showGroupOptions))} /> <label>Groups</label>
                            </div>

                            <div className="acl-container">
                                {Doc.noviceMode ? null : (
                                    <div className="layoutDoc-acls">
                                        <input type="checkbox" onChange={action(() => (this.overrideNested = !this.overrideNested))} checked={this.overrideNested} /> <label>Override Nested </label>
                                        <input type="checkbox" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> <label>Layout</label>
                                    </div>
                                )}
                            </div>
                        </div>
                    ) : (
                        <div className="share-container">
                            <div className="acl-container">
                                <div className="layoutDoc-acls">
                                    <input type="checkbox" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> <label>Layout</label>
                                </div>
                            </div>
                        </div>
                    )}
                    <div className="main-container">
                        <div className={'individual-container'}>
                            <div className="user-sort" onClick={action(() => (this.individualSort = this.individualSort === 'ascending' ? 'descending' : this.individualSort === 'descending' ? 'none' : 'ascending'))}>
                                <div className="title-individual">
                                    Individuals &nbsp;
                                    <FontAwesomeIcon icon={this.individualSort === 'ascending' ? 'caret-up' : this.individualSort === 'descending' ? 'caret-down' : 'caret-right'} size="xs" />
                                </div>
                            </div>
                            <div className="users-list">{userListContents}</div>
                        </div>
                        <div className={'group-container'}>
                            <div className="user-sort" onClick={action(() => (this.groupSort = this.groupSort === 'ascending' ? 'descending' : this.groupSort === 'descending' ? 'none' : 'ascending'))}>
                                <div className="title-group">
                                    Groups &nbsp;
                                    <div className="group-info" onClick={action(() => GroupManager.Instance?.open())}>
                                        <FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} />
                                    </div>
                                    &nbsp;
                                    <FontAwesomeIcon icon={this.groupSort === 'ascending' ? 'caret-up' : this.groupSort === 'descending' ? 'caret-down' : 'caret-right'} size="xs" />
                                </div>
                            </div>
                            <div className={'groups-list'}>{groupListContents}</div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }

    render() {
        return <MainViewModal contents={this.sharingInterface} isDisplayed={this.isOpen} interactive={true} dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity} overlayDisplayedOpacity={this.overlayOpacity} closeOnExternalClick={this.close} />;
    }
}
