import React, {Fragment} from 'react';
import {Link} from 'framework7-react';
import { Device } from '../../web-apps/apps/common/mobile/utils/device';
import {
    AddCommentController,
    EditCommentController,
} from "../../web-apps/apps/common/mobile/lib/controller/collaboration/Comments";

const EditorUIController = () => {
    return null
};

EditorUIController.isSupportEditFeature = () => {
    return true;
};

/**

This is the file where the magic happens.
Try to figure out a working version from a both the old commits
and my hunches from hacking around in the old webapp editor

https://github.com/ONLYOFFICE/web-apps/commit/45a9058da461a9da67ccb389faad08bce8cbda55
*/

EditorUIController.getToolbarOptions = (options) => {
    // console.log('EditorUIController.getToolbarOptions' ,options);
    return (
        <Fragment>
            <Link className={options.disabled && 'disabled'} id='btn-edit' icon='icon-edit-settings' href={false} onClick={() => options.onEditClick()}></Link>
            <Link className={options.disabled && 'disabled'} id='btn-add' icon='icon-plus' href={false} onClick={() => options.onAddClick()}></Link>
        </Fragment>
    );
};

EditorUIController.getUndoRedo = (options) => {
    // console.log('EditorUIController.getUndoRedo', options);
    return (
        <Fragment>
            <Link icon='icon-undo' className={options.disabledUndo && 'disabled'} onClick={() => options.onUndoClick()}></Link>
            <Link icon='icon-redo' className={options.disabledRedo && 'disabled'} onClick={() => options.onRedoClick()}></Link>
        </Fragment>
    );
}

EditorUIController.getEditCommentControllers = () => {
    // console.log('EditorUIController.getEditCommentControllers');
    return (
        <Fragment>
            <AddCommentController />
            <EditCommentController />
        </Fragment>
    );
}

// https://github.com/ONLYOFFICE/web-apps/commit/ee15cf025dd64fe0f48eba015c7bdcea0446a38b
EditorUIController.initFonts = (storeTextSettings) => {
    // console.log('EditorUIController.initFonts', storeTextSettings);
    const api = Common.EditorApi.get();
    api.asc_registerCallback('asc_onInitEditorFonts', (fonts, select) => {
        // console.log('asc_onInitEditorFonts', fonts, select);
        storeTextSettings.initEditorFonts(fonts, select);
    });
    api.asc_registerCallback('asc_onFontFamily', (font) => {
        // console.log('asc_onFontFamily', font);
        storeTextSettings.resetFontName(font);
    });
    api.asc_registerCallback('asc_onFontSize', (size) => {
        // console.log('asc_onFontSize', size);
        storeTextSettings.resetFontSize(size);
    });
    api.asc_registerCallback('asc_onBold', (isBold) => {
        // console.log('asc_onBold', isBold);
        storeTextSettings.resetIsBold(isBold);
    });
    api.asc_registerCallback('asc_onItalic', (isItalic) => {
        // console.log('asc_onItalic', isItalic);
        storeTextSettings.resetIsItalic(isItalic);
    });
    api.asc_registerCallback('asc_onUnderline', (isUnderline) => {
        // console.log('asc_onUnderline', isUnderline);
        storeTextSettings.resetIsUnderline(isUnderline);
    });
    api.asc_registerCallback('asc_onStrikeout', (isStrikeout) => {
        // console.log('asc_onStrikeout', isStrikeout);
        storeTextSettings.resetIsStrikeout(isStrikeout);
    });
};
EditorUIController.initEditorStyles = (storeParagraphSettings) => {
    // console.log('EditorUIController.initEditorStyles', storeParagraphSettings);
    const api = Common.EditorApi.get();
    api.asc_registerCallback('asc_onInitEditorStyles', (styles) => {
        // console.log('asc_onInitEditorStyles', styles);
        storeParagraphSettings.initEditorStyles(styles);
    });
    api.asc_registerCallback('asc_onParaStyleName', (name) => {
        // console.log('asc_onParaStyleName', name);
        storeParagraphSettings.changeParaStyleName(name);
    });
}
EditorUIController.initFocusObjects = (storeFocusObjects) => {
    storeFocusObjects.intf = EditorUIController.Intf(storeFocusObjects);
    // console.log('EditorUIController.initFocusObjects', storeFocusObjects);
    const api = Common.EditorApi.get();
    api.asc_registerCallback('asc_onFocusObject', objects => {
        // console.log('asc_onFocusObject', objects);
        storeFocusObjects.resetFocusObjects(objects);
    });
}
EditorUIController.initTableTemplates = (storeTableSettings) => {
    // console.log('EditorUIController.initTableTemplates', storeTableSettings);
    const api = Common.EditorApi.get();
    api.asc_registerCallback('asc_onInitTableTemplates', (templates) => {
        // console.log('asc_onInitTableTemplates', templates);
        storeTableSettings.initTableTemplates(templates);
    });
}

EditorUIController.initThemeColors = () => {
    // console.log('EditorUIController.initThemeColors');
    const api = Common.EditorApi.get();
    api.asc_registerCallback('asc_onSendThemeColors', (colors, standart_colors) => {
        // console.log('asc_onSendThemeColors', colors, standart_colors);
        Common.Utils.ThemeColor.setColors(colors, standart_colors);
    });
}

EditorUIController.updateChartStyles = (storeChartSettings, storeFocusObjects) => {
    // console.log('EditorUIController.updateChartStyles', storeChartSettings, storeFocusObjects);
    const api = Common.EditorApi.get();
    api.asc_registerCallback('asc_onUpdateChartStyles', () => {
        // console.log('asc_onUpdateChartStyles', storeFocusObjects.chartObject);
        if (storeFocusObjects.chartObject && storeFocusObjects.chartObject.get_ChartProperties()) {
            storeChartSettings.updateChartStyles(api.asc_getChartPreviews(storeFocusObjects.chartObject.get_ChartProperties().getType()));
        }
    });
}

EditorUIController.ContextMenu = {
    // Both those methods are taken from this commit:
    // https://github.com/ONLYOFFICE/web-apps/commit/b0c9a1c5d28371d78ae54854f74f9bdaa8ee9efa
    // 'edit' in handleMenuItemClick is from
    // https://github.com/ONLYOFFICE/web-apps/commit/cb62ade641dbdc2c7a2779d408b6d82bbf738500
    mapMenuItems: (contextMenu) => {
        // console.log('EditorUIController.ContextMenu.mapMenuItems', contextMenu);

        if ( !Common.EditorApi ) return [];

        const { t } = contextMenu.props;
        const _t = t("ContextMenu", { returnObjects: true });

        const { isEdit, canViewComments, canReview, isDisconnected } = contextMenu.props;
        const { isViewer, isProtected } = contextMenu.props;

        // This probably needs to be refired
        if(!isEdit || isViewer || isProtected)
            return EditorUIController.ContextMenu.mapMenuItemsReadOnly(contextMenu);

        const api = Common.EditorApi.get();
        const stack = api.getSelectedElements();
        const canCopy = api.can_CopyCut();

        let itemsIcon = [],
            itemsText = [];

        if ( canCopy ) {
            itemsIcon.push({
                event: 'copy',
                icon: 'icon-copy'
            });
        }

        if ( canViewComments && contextMenu.isComments && !isEdit ) {
            itemsText.push({
                caption: _t.menuViewComment,
                event: 'viewcomment'
            });
        }

        let isText = false,
            isTable = false,
            isImage = false,
            isChart = false,
            isShape = false,
            isLink = false,
            lockedText = false,
            lockedTable = false,
            lockedImage = false,
            lockedHeader = false;

        stack.forEach(item => {
            const objectType = item.get_ObjectType(),
                    objectValue = item.get_ObjectValue();

            if ( objectType == Asc.c_oAscTypeSelectElement.Header ) {
                lockedHeader = objectValue.get_Locked();
            } else
            if ( objectType == Asc.c_oAscTypeSelectElement.Paragraph ) {
                lockedText = objectValue.get_Locked();
                isText = true;
            } else
            if ( objectType == Asc.c_oAscTypeSelectElement.Image ) {
                lockedImage = objectValue.get_Locked();
                if ( objectValue && objectValue.get_ChartProperties() ) {
                    isChart = true;
                } else
                if ( objectValue && objectValue.get_ShapeProperties() ) {
                    isShape = true;
                } else {
                    isImage = true;
                }
            } else
            if ( objectType == Asc.c_oAscTypeSelectElement.Table ) {
                lockedTable = objectValue.get_Locked();
                isTable = true;
            } else
            if ( objectType == Asc.c_oAscTypeSelectElement.Hyperlink ) {
                isLink = true;
            }
        });

        if ( stack.length > 0 ) {
            const swapItems = function(items, indexBefore, indexAfter) {
                items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0];
            };

            if ( isEdit && !isDisconnected ) {
                if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader && canCopy ) {
                    itemsIcon.push({
                        event: 'cut',
                        icon: 'icon-cut'
                    });

                    // Swap 'Copy' and 'Cut'
                    swapItems(itemsIcon, 0, 1);
                }

                if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) {
                    itemsIcon.push({
                        event: 'paste',
                        icon: 'icon-paste'
                    });
                }

                if ( isTable && api.CheckBeforeMergeCells() && !lockedTable && !lockedHeader) {
                    itemsText.push({
                        caption: _t.menuMerge,
                        event: 'merge'
                    });
                }

                if ( isTable && api.CheckBeforeSplitCells() && !lockedTable && !lockedHeader ) {
                    itemsText.push({
                        caption: _t.menuSplit,
                        event: 'split'
                    });
                }

                if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) {
                    itemsText.push({
                        caption: _t.menuDelete,
                        event: 'delete'
                    });
                }

                if ( isTable && !lockedTable && !lockedText && !lockedHeader ) {
                    itemsText.push({
                        caption: _t.menuDeleteTable,
                        event: 'deletetable'
                    });
                }

                if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ){
                    itemsText.push({
                        caption: _t.menuEdit,
                        event: 'edit'
                    });
                }

                if ( !!api.can_AddHyperlink() && !lockedHeader) {
                    itemsText.push({
                        caption: _t.menuAddLink,
                        event: 'addlink'
                    });
                }

                if ( canReview ) {
                    if (contextMenu.inRevisionChange) {
                        itemsText.push({
                            caption: _t.menuReviewChange,
                            event: 'reviewchange'
                        });
                    } else {
                        itemsText.push({
                            caption: _t.menuReview,
                            event: 'review'
                        });
                    }
                }

                if ( contextMenu.isComments && canViewComments ) {
                    itemsText.push({
                        caption: _t.menuViewComment,
                        event: 'viewcomment'
                    });
                }

                const isObject = isShape || isChart || isImage || isTable;
                const hideAddComment = !canViewComments || api.can_AddQuotedComment() === false || lockedText || lockedTable || lockedImage || lockedHeader || (!isText && isObject);
                if ( !hideAddComment ) {
                    itemsText.push({
                        caption: _t.menuAddComment,
                        event: 'addcomment'
                    });
                }
            }
        }

        if ( isLink ) {
            itemsText.push({
                caption: _t.menuOpenLink,
                event: 'openlink'
            });
            itemsText.push({
                caption: _t.menuEditLink,
                event: 'editlink'
            });
        }

        if ( Device.phone && itemsText.length > 2 ) {
            contextMenu.extraItems = itemsText.splice(2,itemsText.length, {
                caption: _t.menuMore,
                event: 'showActionSheet'
            });
        }

        const menuItems = itemsIcon.concat(itemsText);
        // console.log('EditorUIController.ContextMenu.mapMenuItems', menuItems);
        return menuItems;
    } ,
    handleMenuItemClick: (contextMenu, action) => {
        // console.log('EditorUIController.ContextMenu.handleMenuItemClick', contextMenu, action);

        const api = Common.EditorApi.get();
        switch (action) {
            case 'edit':
                setTimeout(() => {
                    contextMenu.props.openOptions('edit');
                }, 400);
                return true;
            case 'addcomment':
                Common.Notifications.trigger('addcomment');
                return true;
            case 'merge':
                api.MergeCells();
                return true;
            case 'delete':
                api.asc_Remove();
                return true;
            case 'deletetable':
                api.remTable();
                return true;
            case 'editlink':
                setTimeout(() => {
                    contextMenu.props.openOptions('edit', 'link');
                }, 400)
                return true;
        }

        return false;
    },
    // This method handles the menu items shown when the user is in edit mode but
    // can't edit the form i.e: in viewer mode or when the document is protected
    // This is mostly a copy of the else statement of ContextMenu.initMenuItems
    // with the bare minimum modifications so it can execute.
    // It is done that way on purpose even if some code ends up duplicated
    // This should make noticing and following Onlyoffice changes easier
    mapMenuItemsReadOnly: (contextMenu) => {
        const { t } = contextMenu.props;
        const _t = t("ContextMenu", {returnObjects: true});

        const { isEdit, canFillForms, isDisconnected, isViewer, canEditComments, isProtected, typeProtection } = contextMenu.props;
        const { isComments, canViewComments, canCoAuthoring, canComments, dataDoc } = contextMenu.props;

        const api = Common.EditorApi.get();
        const inToc = api.asc_GetTableOfContentsPr(true);
        const stack = api.getSelectedElements();
        const canCopy = api.can_CopyCut();
        const docExt = dataDoc ? dataDoc.fileType : '';
        const isAllowedEditing = !isProtected || typeProtection === Asc.c_oAscEDocProtect.TrackedChanges;
        const isAllowedCommenting = typeProtection === Asc.c_oAscEDocProtect.Comments;

        let isText = false,
            isObject = false,
            isLink = false,
            locked = false;

        stack.forEach(item => {
            const objectType = item.get_ObjectType(),
                objectValue = item.get_ObjectValue();
            if ( objectType == Asc.c_oAscTypeSelectElement.Header ) {
                locked = objectValue.get_Locked();
            } else
            if ( objectType == Asc.c_oAscTypeSelectElement.Paragraph ) {
                locked = objectValue.get_Locked();
                isText = true;
            } else
            if ( objectType == Asc.c_oAscTypeSelectElement.Image || objectType == Asc.c_oAscTypeSelectElement.Table) {
                locked = objectValue.get_Locked();
                isObject = true;
            } else if ( objectType == Asc.c_oAscTypeSelectElement.Hyperlink ) {
                isLink = true;
            }
        });

        let itemsIcon = [],
            itemsText = [];

        if (canCopy) {
            itemsIcon.push({
                event: 'copy',
                icon: 'icon-copy'
            });
        }

        if (!isDisconnected) {
            if (canFillForms && canCopy && !locked && (!isViewer || docExt === 'oform') && isAllowedEditing) {
                itemsIcon.push({
                    event: 'cut',
                    icon: 'icon-cut'
                });
            }

            if (canFillForms && canCopy && !locked && (!isViewer || docExt === 'oform') && isAllowedEditing) {
                itemsIcon.push({
                    event: 'paste',
                    icon: 'icon-paste'
                });
            }

            if (canViewComments && isComments) {
                itemsText.push({
                    caption: _t.menuViewComment,
                    event: 'viewcomment'
                });
            }

            if (api.can_AddQuotedComment() !== false && canCoAuthoring && canComments && !locked && !(!isText && isObject) && (!isViewer || canEditComments) && (isAllowedEditing || isAllowedCommenting)) {
                itemsText.push({
                    caption: _t.menuAddComment,
                    event: 'addcomment'
                });
            }
        }

        if (isLink) {
            itemsText.push({
                caption: _t.menuOpenLink,
                event: 'openlink'
            });

            if(isAllowedEditing && !isViewer) {
                itemsText.push({
                    caption: t('ContextMenu.menuEditLink'),
                    event: 'editlink'
                });
            }
        }

        if(inToc && isEdit && !isViewer && isAllowedEditing) {
            itemsText.push({
                caption: t('ContextMenu.textRefreshEntireTable'),
                event: 'refreshEntireTable'
            });
            itemsText.push({
                caption: t('ContextMenu.textRefreshPageNumbersOnly'),
                event: 'refreshPageNumbers'
            });
        }

        return itemsIcon.concat(itemsText);
    }
};

// This objects holds the mysterious functions in focusObjects.js inside the intf object
// These for now are based on the latest valid implementation from the mobile editor
// The easiest way to fix it was to restores those in focusObjects.js: A way to improve would be to do that here.
// https://github.com/ONLYOFFICE/web-apps/commit/b0c9a1c5d28371d78ae54854f74f9bdaa8ee9efa
// https://github.com/ONLYOFFICE/web-apps/blame/bc7713368a787e01a0ce93a2d7956c77c762e1c5/apps/documenteditor/mobile/src/store/focusObjects.js (for settings or filterFocusObjects)

EditorUIController.Intf = function (storeFocusObjects) {
    var obj = {};

    // console.log(window.Asc.c_oAscTypeSelectElement);

    obj.filterFocusObjects = () => {
        const _settings = [];
        for (let object of storeFocusObjects._focusObjects) {
            let type = object.get_ObjectType();
            if (Asc.c_oAscTypeSelectElement.Paragraph === type) {
                _settings.push('text', 'paragraph');
            } else if (Asc.c_oAscTypeSelectElement.Table === type) {
                _settings.push('table');
            } else if (Asc.c_oAscTypeSelectElement.Image === type) {
                if (object.get_ObjectValue().get_ChartProperties()) {
                    // Exclude shapes if chart exist
                    let si = _settings.indexOf('shape');
                    si < 0 ? _settings.push('chart') : _settings.splice(si,1,'chart');
                } else if (object.get_ObjectValue().get_ShapeProperties() && !_settings.includes('chart')) {
                    _settings.push('shape');
                } else {
                    _settings.push('image');
                }
            } else if (Asc.c_oAscTypeSelectElement.Hyperlink === type) {
                _settings.push('hyperlink');
            } else if (Asc.c_oAscTypeSelectElement.Header === type) {
                _settings.push('header');
            }
        }
        return _settings.filter((value, index, self) => self.indexOf(value) === index);
    }

    obj.getHeaderObject = () => {
        const headers = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Header) {
                headers.push(object);
            }
        }
        if (headers.length > 0) {
            const object = headers[headers.length - 1]; // get top
            return object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    obj.getParagraphObject = () => {
        const paragraphs = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) {
                paragraphs.push(object);
            }
        }
        if (paragraphs.length > 0) {
            const object = paragraphs[paragraphs.length - 1]; // get top
            return object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    obj.getShapeObject = () => {
        const shapes = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Image) {
                if (object.get_ObjectValue()
                    && typeof object.get_ObjectValue().get_ShapeProperties === "function"
                    && object.get_ObjectValue().get_ShapeProperties()) {
                    shapes.push(object);
                }
            }
        }
        if (shapes.length > 0) {
            const object = shapes[shapes.length - 1]; // get top
            return object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    obj.getImageObject = () => {
        const images = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image) {
                const imageObject = object.get_ObjectValue();
                if (imageObject && imageObject.get_ShapeProperties() === null && imageObject.get_ChartProperties() === null) {
                    images.push(object);
                }
            }
        }
        if (images.length > 0) {
            const object = images[images.length - 1]; // get top
            return object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    obj.getTableObject = () => {
        const tables = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) {
                tables.push(object);
            }
        }
        if (tables.length > 0) {
            const object = tables[tables.length - 1]; // get top table
            return object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    obj.getChartObject = () => {
        const charts = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectValue()
                && typeof object.get_ObjectValue().get_ChartProperties === 'function'
                && object.get_ObjectValue().get_ChartProperties() ) {
                charts.push(object);
            }
        }
        if (charts.length > 0) {
            const object = charts[charts.length - 1]; // get top table
            return object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    obj.getLinkObject = () => {
        const links = [];
        for (let object of storeFocusObjects._focusObjects) {
            if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
                links.push(object);
            }
        }
        if (links.length > 0) {
            const object = links[links.length - 1]; // get top
            return  object.get_ObjectValue();
        } else {
            return undefined;
        }
    }

    return obj;
}

export default EditorUIController;
