import { DOMOutputSpec, MarkSpec } from 'prosemirror-model';
import { ClientUtils } from '../../../../ClientUtils';
import { Utils } from '../../../../Utils';
const emDOM: DOMOutputSpec = ['em', 0];
const strongDOM: DOMOutputSpec = ['strong', 0];
const codeDOM: DOMOutputSpec = ['code', 0];
// :: Object [Specs](#model.MarkSpec) for the marks in the schema.
export const marks: { [index: string]: MarkSpec } = {
    splitter: {
        attrs: {
            id: { default: '' },
        },
        toDOM() {
            return ['div', { className: 'dummy' }, 0];
        },
    },
    // :: MarkSpec an autoLinkAnchor. These are automatically generated anchors to "published" documents based on the anchor text matching the
    // published document's title.
    // NOTE: unlike linkAnchors, the autoLinkAnchor's href's indicate the target anchor of the hyperlink and NOT the source.  This is because
    // automatic links do not create a text selection Marker document for the source anchor, but use the text document itself.  Since
    // multiple automatic links can be created each having the same source anchor (the whole document), the target href of the link is needed to
    // disambiguate links from one another.
    // Rendered and parsed as an ``
    // element.
    autoLinkAnchor: {
        attrs: {
            allAnchors: { default: [] as { href: string; title: string; anchorId: string }[] },
            title: { default: null },
        },
        inclusive: false,
        parseDOM: [
            {
                tag: 'a[href]',
                getAttrs: dom => {
                    return {
                        title: dom.getAttribute('title'),
                    };
                },
            },
        ],
        toDOM: node => {
            const targethrefs = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.href : item.href), '');
            const anchorids = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.anchorId : item.anchorId), '');
            return ['a', { id: Utils.GenerateGuid(), class: anchorids, 'data-targethrefs': targethrefs, /* 'data-noPreview': 'true', */ 'data-linkdoc': node.attrs.linkDoc, title: node.attrs.title, style: `background: lightBlue` }, 0];
        },
    },
    noAutoLinkAnchor: {
        attrs: {},
        inclusive: false,
        parseDOM: [
            {
                tag: 'div',
                getAttrs: dom => {
                    return {
                        noAutoLink: dom.getAttribute('data-noAutoLink'),
                    };
                },
            },
        ],
        toDOM() {
            return ['span', { 'data-noAutoLink': 'true' }, 0];
        },
    },
    // :: MarkSpec A linkAnchor. The anchor can have multiple links, where each linkAnchor specifies an href to the URL of the source selection Marker text,
    // and a title for use in menus and hover. `title`
    // defaults to the empty string. Rendered and parsed as an ``
    // element.
    linkAnchor: {
        attrs: {
            allAnchors: { default: [] as { href: string; title: string; anchorId: string }[] },
            title: { default: null },
            noPreview: { default: false },
            fontSize: { default: null },
            docref: { default: false }, // flags whether the linked text comes from a document within Dash.  If so, an attribution label is appended after the text
        },
        inclusive: false,
        parseDOM: [
            {
                tag: 'a[href]',
                getAttrs: dom => {
                    return {
                        title: dom.getAttribute('title'),
                        noPreview: dom.getAttribute('noPreview'),
                    };
                },
            },
        ],
        toDOM: node => {
            const targethrefs = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.href : item.href), '');
            const anchorids = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.anchorId : item.anchorId), '');
            return node.attrs.docref && node.attrs.title
                ? [
                      'a',
                      ['span', 0],
                      [
                          'span',
                          {
                              ...node.attrs,
                              class: 'prosemirror-attribution',
                              'data-targethrefs': targethrefs,
                              href: node.attrs.allAnchors[0].href,
                              style: `font-size: ${node.attrs.fontSize}`,
                          },
                          node.attrs.title,
                      ],
                  ]
                : ['a', { id: '' + Utils.GenerateGuid(), class: anchorids, 'data-targethrefs': targethrefs, title: node.attrs.title, 'data-noPreview': node.attrs.noPreview, style: `text-decoration: underline; cursor: default` }, 0];
        },
    },
    /** FONT SIZES */
    pFontSize: {
        attrs: { fontSize: { default: '10px' } },
        parseDOM: [
            {
                tag: 'span',
                getAttrs: dom => {
                    return { fontSize: dom.style.fontSize ? dom.style.fontSize.toString() : '' };
                },
            },
        ],
        toDOM: node => (node.attrs.fontSize ? ['span', { style: `font-size: ${node.attrs.fontSize};` }] : ['span', 0]),
    },
    /* FONTS */
    pFontFamily: {
        attrs: { fontFamily: { default: '' } },
        parseDOM: [
            {
                tag: 'span',
                getAttrs: dom => {
                    const cstyle = getComputedStyle(dom);
                    if (cstyle.font) {
                        if (cstyle.font.indexOf('Times New Roman') !== -1) return { fontFamily: 'Times New Roman' };
                        if (cstyle.font.indexOf('Arial') !== -1) return { fontFamily: 'Arial' };
                        if (cstyle.font.indexOf('Georgia') !== -1) return { fontFamily: 'Georgia' };
                        if (cstyle.font.indexOf('Comic Sans') !== -1) return { fontFamily: 'Comic Sans MS' };
                        if (cstyle.font.indexOf('Tahoma') !== -1) return { fontFamily: 'Tahoma' };
                        if (cstyle.font.indexOf('Crimson') !== -1) return { fontFamily: 'Crimson Text' };
                    }
                    return { fontFamily: '' };
                },
            },
        ],
        toDOM: node => (node.attrs.fontFamily ? ['span', { style: `font-family: "${node.attrs.fontFamily}";` }] : ['span', 0]),
    },
    // :: MarkSpec Coloring on text. Has `color` attribute that defined the color of the marked text.
    pFontColor: {
        attrs: { fontColor: { default: '' } },
        inclusive: true,
        parseDOM: [
            {
                tag: 'span',
                getAttrs: dom => {
                    return { color: dom.getAttribute('color') };
                },
            },
        ],
        toDOM: node => (node.attrs.fontColor ? ['span', { style: 'color:' + node.attrs.fontColor }] : ['span', 0]),
    },
    pFontHighlight: {
        attrs: {
            fontHighlight: { default: 'transparent' },
        },
        inclusive: true,
        parseDOM: [
            {
                tag: 'span',
                getAttrs: dom => {
                    return { fontHighlight: dom.getAttribute('background-color') };
                },
            },
        ],
        toDOM: node => {
            return node.attrs.fontHighlight ? ['span', { style: 'background-color:' + node.attrs.fontHighlight }] : ['span', { style: 'background-color: transparent' }];
        },
    },
    // :: MarkSpec An emphasis mark. Rendered as an `` element.
    // Has parse rules that also match `` and `font-style: italic`.
    em: {
        parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style: italic' }],
        toDOM() {
            return emDOM;
        },
    },
    // :: MarkSpec A strong mark. Rendered as ``, parse rules
    // also match `` and `font-weight: bold`.
    strong: {
        parseDOM: [{ tag: 'strong' }, { tag: 'b' }, { style: 'font-weight' }],
        toDOM() {
            return strongDOM;
        },
    },
    strikethrough: {
        parseDOM: [{ tag: 'strike' }, { style: 'text-decoration=line-through' }, { style: 'text-decoration-line=line-through' }],
        toDOM: () => [
            'span',
            {
                style: 'text-decoration-line:line-through',
            },
        ],
    },
    subscript: {
        excludes: 'superscript',
        parseDOM: [{ tag: 'sub' }, { style: 'vertical-align=sub' }],
        toDOM: () => ['sub'],
    },
    superscript: {
        excludes: 'subscript',
        parseDOM: [{ tag: 'sup' }, { style: 'vertical-align=super' }],
        toDOM: () => ['sup'],
    },
    mbulletType: {
        attrs: {
            bulletType: { default: 'decimal' },
        },
        toDOM: node => {
            return [
                'span',
                {
                    style: `background: ${node.attrs.bulletType === 'decimal' ? 'yellow' : node.attrs.bulletType === 'upper-alpha' ? 'blue' : 'green'}`,
                },
            ];
        },
    },
    summarizeInclusive: {
        parseDOM: [
            {
                tag: 'span',
                getAttrs: p => {
                    if (typeof p !== 'string') {
                        const style = getComputedStyle(p);
                        if (style.textDecoration === 'underline') return null;
                        if (p.parentElement?.outerHTML.indexOf('text-decoration: underline') !== -1 && p.parentElement?.outerHTML.indexOf('text-decoration-style: solid') !== -1) {
                            return null;
                        }
                    }
                    return false;
                },
            },
        ],
        inclusive: true,
        toDOM() {
            return [
                'span',
                {
                    style: 'text-decoration: underline; text-decoration-style: solid; text-decoration-color: rgba(204, 206, 210, 0.92)',
                },
            ];
        },
    },
    summarize: {
        inclusive: false,
        parseDOM: [
            {
                tag: 'span',
                getAttrs: p => {
                    if (typeof p !== 'string') {
                        const style = getComputedStyle(p);
                        if (style.textDecoration === 'underline') return null;
                        if (p.parentElement?.outerHTML.indexOf('text-decoration: underline') !== -1 && p.parentElement?.outerHTML.indexOf('text-decoration-style: dotted') !== -1) {
                            return null;
                        }
                    }
                    return false;
                },
            },
        ],
        toDOM() {
            return [
                'span',
                {
                    style: 'text-decoration: underline; text-decoration-style: dotted; text-decoration-color: rgba(204, 206, 210, 0.92)',
                },
            ];
        },
    },
    underline: {
        parseDOM: [
            {
                tag: 'span',
                getAttrs: p => {
                    if (typeof p !== 'string') {
                        const style = getComputedStyle(p);
                        if (style.textDecoration === 'underline' || p.parentElement?.outerHTML.indexOf('text-decoration-style:line') !== -1) {
                            return null;
                        }
                    }
                    return false;
                },
            },
            // { style: "text-decoration=underline" }
        ],
        toDOM: () => [
            'span',
            {
                style: 'text-decoration:underline;text-decoration-style:line',
            },
        ],
    },
    search_highlight: {
        attrs: {
            selected: { default: false },
        },
        parseDOM: [{ style: 'background: yellow' }],
        toDOM: node => {
            return ['span', { style: `background: ${node.attrs.selected ? 'orange' : 'yellow'}` }];
        },
    },
    // the id of the user who entered the text
    user_mark: {
        attrs: {
            userid: { default: '' },
            modified: { default: 'when?' }, // 1 second intervals since 1970
        },
        excludes: 'user_mark',
        group: 'inline',
        toDOM: node => {
            const uid = node.attrs.userid.replace(/\./g, '').replace(/@/g, '');
            const min = Math.round(node.attrs.modified / 60);
            const hr = Math.round(min / 60);
            const day = Math.round(hr / 60 / 24);
            const remote = node.attrs.userid !== ClientUtils.CurrentUserEmail() ? ' UM-remote' : '';
            return ['span', { class: 'UM-' + uid + remote + ' UM-min-' + min + ' UM-hr-' + hr + ' UM-day-' + day }, 0];
        },
    },
    // the id of the user who entered the text
    user_tag: {
        attrs: {
            userid: { default: '' },
            modified: { default: 'when?' }, // 1 second intervals since 1970
            tag: { default: '' },
        },
        group: 'inline',
        inclusive: false,
        toDOM: node => {
            const uid = node.attrs.userid.replace('.', '').replace('@', '');
            return ['span', { class: 'UT-' + uid + ' UT-' + node.attrs.tag }, 0];
        },
    },
    // :: MarkSpec Code font mark. Represented as a `` element.
    code: {
        parseDOM: [{ tag: 'code' }],
        toDOM() {
            return codeDOM;
        },
    },
};