import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from "react";
import { EditorState, convertToRaw, Modifier } from "draft-js";
import draftToHtml from "draftjs-to-html";
import { DataUtilities } from "../../Common/DataUtilities";
import { XValueEditor } from "../DataEditing";
import { TestContext } from "../../Tester/TestContext";
import { TestingConstants } from "../Testing/TestingConstants";
import { Tooltip } from "@material-ui/core";
import { AttentionIcon } from "../Icon/AttentionIcon";
import { TextMergeConstants } from "./TextMergeConstants";
export class TextMergeUtility {
    static MergeToPlainText(document, getValueByKey) {
        let content = editorFormats.rawDraftContentState(document);
        let results = [];
        for (let block of content.blocks) {
            let text = block.text;
            let baseText = [];
            let entities = content.entityMap;
            let entityRanges = block.entityRanges;
            if (entityRanges.length === 0) {
                baseText.push(text);
            }
            entityRanges.forEach((entityRange, index) => {
                let { offset } = entityRange;
                if (index === 0) {
                    baseText.push(text.slice(0, offset));
                }
                else if (index > 0 && index !== entityRanges.length - 1) {
                    let previousOffset = entityRanges[index - 1].offset;
                    baseText.push(text.slice(previousOffset + 1, offset));
                }
                if (index > 0 && index === entityRanges.length - 1) {
                    let previousOffset = entityRanges[index - 1].offset;
                    baseText.push(text.slice(previousOffset + 1, offset));
                    baseText.push(text.slice(offset));
                }
            });
            entityRanges.forEach((entityRange, index) => {
                let { key } = entityRange;
                let entityData = entities[key].data;
                if (getValueByKey) {
                    let value = getValueByKey(entityData.key);
                    baseText[index] += value;
                }
            });
            results.push(baseText.join());
        }
        return results.join();
    }
    static MergeToHTML(document, data) {
        let resultHTML = draftToHtml(convertToRaw(document.getCurrentContent()), undefined, undefined, (entity, ...args) => {
            if (entity.type === TextMergeConstants.MERGE_TEXT_ENTITY_TYPE) {
                let value = DataUtilities.get(data, entity.data.fieldpath);
                let style = entity.data.styles;
                const styleString = Object.entries(style || {})
                    .map(([k, v]) => {
                    k = k.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
                    return `${k}:${v}`;
                })
                    .join(";");
                return `<xfield style="${styleString}">${(value === null || value === void 0 ? void 0 : value.toString()) || ""}</xfield>`;
            }
        });
        return resultHTML;
    }
    static compareNodeAttributes(a, b) {
        let tempA = a.cloneNode(true);
        let tempB = b.cloneNode(true);
        // remove all children of tempA
        for (let node of tempA.childNodes) {
            tempA.removeChild(node);
        }
        // add all children of tempB to tempA
        for (let node of tempB.childNodes) {
            tempB.appendChild(node.cloneNode(true));
        }
        return tempA.isEqualNode(tempB);
    }
    static ApplyStylesToMergeText(resultHTML) {
        return resultHTML;
    }
    static MergeToPDF(document, values) {
        return "";
    }
}
export const VariableRenderStrategy = (contentBlock, callback, contentState) => {
    contentBlock.findEntityRanges((character) => {
        const entityKey = character.getEntity();
        return (entityKey !== null &&
            contentState.getEntity(entityKey).getType() === TextMergeConstants.MERGE_TEXT_ENTITY_TYPE);
    }, callback);
};
export const VariableRender = (props) => {
    return _jsx(VariableRenderEntity, Object.assign({}, props), void 0);
};
export const VariableRenderEntity = (props) => {
    const { entityKey, contentState } = props;
    const { fieldpath, showModalWithEntity, isValidField } = contentState.getEntity(entityKey).getData();
    const testContext = React.useContext(TestContext);
    const isvalid = isValidField(fieldpath);
    const onClick = () => {
        showModalWithEntity(entityKey);
    };
    if (testContext) {
        const testitem = testContext.findItem(fieldpath);
        if (!testitem || (testitem === null || testitem === void 0 ? void 0 : testitem.isError)) {
            return (_jsx(Tooltip, Object.assign({ title: (testitem === null || testitem === void 0 ? void 0 : testitem.result) || "" }, { children: _jsxs("span", Object.assign({ style: {
                        borderRadius: 5,
                        background: TestingConstants.BACKGROUND_FAIL,
                        position: "relative",
                    } }, { children: [props.children, " ", fieldpath, " \u00A0", _jsx("span", Object.assign({ style: { position: "absolute", bottom: 0, right: 0 } }, { children: _jsx(AttentionIcon, {}, void 0) }), void 0)] }), void 0) }), void 0));
        }
        return (_jsxs("span", Object.assign({ style: {
                borderRadius: 5,
                background: TestingConstants.BACKGROUND_SUCCESS,
                position: "relative",
            } }, { children: [props.children, " ", fieldpath, " \u00A0", _jsx("span", Object.assign({ style: {
                        position: "absolute",
                        top: "100%",
                        right: 0,
                        color: TestingConstants.TEXT_SUCCESS,
                        fontSize: 8,
                    } }, { children: testitem.result }), void 0)] }), void 0));
    }
    return (_jsxs("span", Object.assign({ onMouseDown: onClick, style: {
            borderRadius: 5,
            background: isvalid ? "#e0e0e0" : "red",
        } }, { children: [props.children, " ", fieldpath, " \u00A0"] }), void 0));
};
export const variableRenderPlugin = {
    decorators: [
        {
            strategy: VariableRenderStrategy,
            component: VariableRender,
        },
    ],
};
const TempVariableRenderStrategy = (contentBlock, callback, contentState) => {
    contentBlock.findEntityRanges((character) => {
        const entityKey = character.getEntity();
        return (entityKey !== null &&
            contentState.getEntity(entityKey).getType() === TextMergeConstants.MERGE_TEXT_TEMP_ENTITY_TYPE);
    }, callback);
};
const TempVariableRenderEntity = (props) => {
    const { entityKey, contentState } = props;
    const { fieldpath } = contentState.getEntity(entityKey).getData();
    return (_jsxs("span", Object.assign({ style: {
            borderRadius: 5,
            border: "dotted 1px #777",
            color: "#777",
        } }, { children: [props.children, " ", fieldpath, " \u00A0"] }), void 0));
};
const TempVariableRender = (props) => {
    return _jsx(TempVariableRenderEntity, Object.assign({}, props), void 0);
};
export const tempVariableRenderPlugin = {
    decorators: [
        {
            strategy: TempVariableRenderStrategy,
            component: TempVariableRender,
        },
    ],
};
export const ValueEditorRenderStrategy = (contentBlock, callback, contentState) => {
    contentBlock.findEntityRanges((character) => {
        const entityKey = character.getEntity();
        return (entityKey !== null &&
            contentState.getEntity(entityKey).getType() === TextMergeConstants.MERGE_TEXT_ENTITY_TYPE);
    }, callback);
};
export const ValueEditorRender = (props) => {
    // const { elementType } = props.contentState.getEntity(props.entityKey).getData();
    return _jsx(ValueEditorRenderEntity, Object.assign({}, props), void 0);
};
export const ValueEditorRenderEntity = (props) => {
    const { entityKey, contentState } = props;
    const { field, value, onUpdateValue, fieldpath } = contentState.getEntity(entityKey).getData();
    const onUpdate = (newValue) => {
        onUpdateValue(fieldpath, newValue);
    };
    return (_jsx("div", Object.assign({ style: { display: "inline-block" } }, { children: _jsx(XValueEditor, { forData: field, onUpdate: onUpdate, mode: "edit_mode", value: value }, void 0) }), void 0));
};
export const valueEditorPlugin = {
    decorators: [
        {
            strategy: ValueEditorRenderStrategy,
            component: ValueEditorRender,
        },
    ],
};
export const getEntityRange = (editorState, entityKey) => {
    const selection = editorState.getSelection();
    const currentContent = editorState.getCurrentContent();
    const startKey = selection.getStartKey();
    let block = currentContent.getBlockForKey(startKey);
    let range;
    block.findEntityRanges((character) => {
        const key = character.getEntity();
        return key !== null && entityKey === key;
    }, (start, end) => {
        range = {
            start,
            end,
        };
    });
    return range;
};
// HTML
export const addEntity = (editorState, entityType, text, data) => {
    let selection = editorState.getSelection();
    let blockKey = selection.getAnchorKey();
    let block = editorState.getCurrentContent().getBlockForKey(blockKey);
    const currentEntity = block.getEntityAt(selection.getAnchorOffset());
    if (currentEntity) {
        const entityRange = getEntityRange(editorState, currentEntity);
        if (entityRange) {
            const isBackward = selection.getIsBackward();
            if (isBackward) {
                selection = selection.merge({
                    anchorOffset: entityRange.end,
                    focusOffset: entityRange.start,
                });
            }
            else {
                selection = selection.merge({
                    anchorOffset: entityRange.start,
                    focusOffset: entityRange.end,
                });
            }
        }
    }
    const entityKey = editorState
        .getCurrentContent()
        .createEntity(entityType, "IMMUTABLE", data)
        .getLastCreatedEntityKey();
    let contentState = Modifier.replaceText(editorState.getCurrentContent(), selection, `${text}`, editorState.getCurrentInlineStyle(), entityKey);
    let newEditorState = EditorState.push(editorState, contentState, "insert-characters");
    // insert a blank space after link
    selection = newEditorState.getSelection().merge({
        anchorOffset: selection.get("anchorOffset") + text.length,
        focusOffset: selection.get("anchorOffset") + text.length,
    });
    newEditorState = EditorState.acceptSelection(newEditorState, selection);
    contentState = Modifier.insertText(newEditorState.getCurrentContent(), selection, " ", newEditorState.getCurrentInlineStyle(), undefined);
    return [EditorState.push(newEditorState, contentState, "insert-characters"), entityKey];
};
export const editorFormats = {
    rawDraftContentState: (editorState) => convertToRaw(editorState.getCurrentContent()),
    html: (editorState) => {
        const htmlOut = draftToHtml(editorFormats.rawDraftContentState(editorState));
        return htmlOut;
    },
};
//# sourceMappingURL=XTextMergeUtilities.js.map