
/* IMPORT */

import {mergeMaps} from './utils';

/* ELEMENTS */

const HTML_ELEMENTS_ALLOW = [
  'a',
  'abbr',
  'acronym',
  'address',
  'area',
  'article',
  'aside',
  'audio',
  'b',
  'bdi',
  'bdo',
  'bgsound',
  'big',
  'blockquote',
  'body',
  'br',
  'button',
  'canvas',
  'caption',
  'center',
  'cite',
  'code',
  'col',
  'colgroup',
  'datalist',
  'dd',
  'del',
  'details',
  'dfn',
  'dialog',
  'dir',
  'div',
  'dl',
  'dt',
  'em',
  'fieldset',
  'figcaption',
  'figure',
  'font',
  'footer',
  'form',
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6',
  'head',
  'header',
  'hgroup',
  'hr',
  'html',
  'i',
  'img',
  'input',
  'ins',
  'kbd',
  'keygen',
  'label',
  'layer',
  'legend',
  'li',
  'link',
  'listing',
  'main',
  'map',
  'mark',
  'marquee',
  'menu',
  'meta',
  'meter',
  'nav',
  'nobr',
  'ol',
  'optgroup',
  'option',
  'output',
  'p',
  'picture',
  'popup',
  'pre',
  'progress',
  'q',
  'rb',
  'rp',
  'rt',
  'rtc',
  'ruby',
  's',
  'samp',
  'section',
  'select',
  'selectmenu',
  'small',
  'source',
  'span',
  'strike',
  'strong',
  'style',
  'sub',
  'summary',
  'sup',
  'table',
  'tbody',
  'td',
  'tfoot',
  'th',
  'thead',
  'time',
  'tr',
  'track',
  'tt',
  'u',
  'ul',
  'var',
  'video',
  'wbr'
];

const HTML_ELEMENTS_DISALLOW = [
  'basefont',
  'command',
  'data',
  'iframe',
  'image',
  'plaintext',
  'portal',
  'slot',
  // 'template', //TODO: Not exactly correct to never allow this, too strict
  'textarea',
  'title',
  'xmp'
];

const HTML_ELEMENTS = new Set ([
  ...HTML_ELEMENTS_ALLOW,
  ...HTML_ELEMENTS_DISALLOW
]);

const SVG_ELEMENTS_ALLOW = [
  'svg',
  'a',
  'altglyph',
  'altglyphdef',
  'altglyphitem',
  'animatecolor',
  'animatemotion',
  'animatetransform',
  'circle',
  'clippath',
  'defs',
  'desc',
  'ellipse',
  'filter',
  'font',
  'g',
  'glyph',
  'glyphref',
  'hkern',
  'image',
  'line',
  'lineargradient',
  'marker',
  'mask',
  'metadata',
  'mpath',
  'path',
  'pattern',
  'polygon',
  'polyline',
  'radialgradient',
  'rect',
  'stop',
  'style',
  'switch',
  'symbol',
  'text',
  'textpath',
  'title',
  'tref',
  'tspan',
  'view',
  'vkern',
  /* FILTERS */
  'feBlend',
  'feColorMatrix',
  'feComponentTransfer',
  'feComposite',
  'feConvolveMatrix',
  'feDiffuseLighting',
  'feDisplacementMap',
  'feDistantLight',
  'feFlood',
  'feFuncA',
  'feFuncB',
  'feFuncG',
  'feFuncR',
  'feGaussianBlur',
  'feImage',
  'feMerge',
  'feMergeNode',
  'feMorphology',
  'feOffset',
  'fePointLight',
  'feSpecularLighting',
  'feSpotLight',
  'feTile',
  'feTurbulence'
];

const SVG_ELEMENTS_DISALLOW = [
  'animate',
  'color-profile',
  'cursor',
  'discard',
  'fedropshadow',
  'font-face',
  'font-face-format',
  'font-face-name',
  'font-face-src',
  'font-face-uri',
  'foreignobject',
  'hatch',
  'hatchpath',
  'mesh',
  'meshgradient',
  'meshpatch',
  'meshrow',
  'missing-glyph',
  'script',
  'set',
  'solidcolor',
  'unknown',
  'use'
];

const SVG_ELEMENTS = new Set ([
  ...SVG_ELEMENTS_ALLOW,
  ...SVG_ELEMENTS_DISALLOW
]);

const MATH_ELEMENTS_ALLOW = [
  'math',
  'menclose',
  'merror',
  'mfenced',
  'mfrac',
  'mglyph',
  'mi',
  'mlabeledtr',
  'mmultiscripts',
  'mn',
  'mo',
  'mover',
  'mpadded',
  'mphantom',
  'mroot',
  'mrow',
  'ms',
  'mspace',
  'msqrt',
  'mstyle',
  'msub',
  'msup',
  'msubsup',
  'mtable',
  'mtd',
  'mtext',
  'mtr',
  'munder',
  'munderover'
];

const MATH_ELEMENTS_DISALLOW = [
  'maction',
  'maligngroup',
  'malignmark',
  'mlongdiv',
  'mscarries',
  'mscarry',
  'msgroup',
  'mstack',
  'msline',
  'msrow',
  'semantics',
  'annotation',
  'annotation-xml',
  'mprescripts',
  'none'
];

const MATH_ELEMENTS = new Set ([
  ...MATH_ELEMENTS_ALLOW,
  ...MATH_ELEMENTS_DISALLOW
]);

/* ATTRIBUTES */

const HTML_ATTRIBUTES_ALLOW = [
  'abbr',
  'accept',
  'accept-charset',
  'accesskey',
  'action',
  'align',
  'alink',
  'allow',
  'allowfullscreen',
  'alt',
  'anchor',
  'archive',
  'as',
  'async',
  'autocapitalize',
  'autocomplete',
  'autocorrect',
  'autofocus',
  'autopictureinpicture',
  'autoplay',
  'axis',
  'background',
  'behavior',
  'bgcolor',
  'border',
  'bordercolor',
  'capture',
  'cellpadding',
  'cellspacing',
  'challenge',
  'char',
  'charoff',
  'charset',
  'checked',
  'cite',
  'class',
  'classid',
  'clear',
  'code',
  'codebase',
  'codetype',
  'color',
  'cols',
  'colspan',
  'compact',
  'content',
  'contenteditable',
  'controls',
  'controlslist',
  'conversiondestination',
  'coords',
  'crossorigin',
  'csp',
  'data',
  'datetime',
  'declare',
  'decoding',
  'default',
  'defer',
  'dir',
  'direction',
  'dirname',
  'disabled',
  'disablepictureinpicture',
  'disableremoteplayback',
  'disallowdocumentaccess',
  'download',
  'draggable',
  'elementtiming',
  'enctype',
  'end',
  'enterkeyhint',
  'event',
  'exportparts',
  'face',
  'for',
  'form',
  'formaction',
  'formenctype',
  'formmethod',
  'formnovalidate',
  'formtarget',
  'frame',
  'frameborder',
  'headers',
  'height',
  'hidden',
  'high',
  'href',
  'hreflang',
  'hreftranslate',
  'hspace',
  'http-equiv',
  'id',
  'imagesizes',
  'imagesrcset',
  'importance',
  'impressiondata',
  'impressionexpiry',
  'incremental',
  'inert',
  'inputmode',
  'integrity',
  'invisible',
  'ismap',
  'keytype',
  'kind',
  'label',
  'lang',
  'language',
  'latencyhint',
  'leftmargin',
  'link',
  'list',
  'loading',
  'longdesc',
  'loop',
  'low',
  'lowsrc',
  'manifest',
  'marginheight',
  'marginwidth',
  'max',
  'maxlength',
  'mayscript',
  'media',
  'method',
  'min',
  'minlength',
  'multiple',
  'muted',
  'name',
  'nohref',
  'nomodule',
  'nonce',
  'noresize',
  'noshade',
  'novalidate',
  'nowrap',
  'object',
  'open',
  'optimum',
  'part',
  'pattern',
  'ping',
  'placeholder',
  'playsinline',
  'policy',
  'poster',
  'preload',
  'pseudo',
  'readonly',
  'referrerpolicy',
  'rel',
  'reportingorigin',
  'required',
  'resources',
  'rev',
  'reversed',
  'role',
  'rows',
  'rowspan',
  'rules',
  'sandbox',
  'scheme',
  'scope',
  'scopes',
  'scrollamount',
  'scrolldelay',
  'scrolling',
  'select',
  'selected',
  'shadowroot',
  'shadowrootdelegatesfocus',
  'shape',
  'size',
  'sizes',
  'slot',
  'span',
  'spellcheck',
  'src',
  'srclang',
  'srcset',
  'standby',
  'start',
  'step',
  'style',
  'summary',
  'tabindex',
  'target',
  'text',
  'title',
  'topmargin',
  'translate',
  'truespeed',
  'trusttoken',
  'type',
  'usemap',
  'valign',
  'value',
  'valuetype',
  'version',
  'virtualkeyboardpolicy',
  'vlink',
  'vspace',
  'webkitdirectory',
  'width',
  'wrap'
];

const HTML_ATTRIBUTES_DISALLOW = [
  'allowpaymentrequest',
  'is'
];

const HTML_ATTRIBUTES = new Set ([
  ...HTML_ATTRIBUTES_ALLOW,
  ...HTML_ATTRIBUTES_DISALLOW
]);

const SVG_ATTRIBUTES_ALLOW = [
  'accent-height',
  'accumulate',
  'additive',
  'alignment-baseline',
  'ascent',
  'attributename',
  'attributetype',
  'azimuth',
  'basefrequency',
  'baseline-shift',
  'begin',
  'bias',
  'by',
  'class',
  'clip',
  'clippathunits',
  'clip-path',
  'clip-rule',
  'color',
  'color-interpolation',
  'color-interpolation-filters',
  'color-profile',
  'color-rendering',
  'cx',
  'cy',
  'd',
  'dx',
  'dy',
  'diffuseconstant',
  'direction',
  'display',
  'divisor',
  'dominant-baseline',
  'dur',
  'edgemode',
  'elevation',
  'end',
  'fill',
  'fill-opacity',
  'fill-rule',
  'filter',
  'filterunits',
  'flood-color',
  'flood-opacity',
  'font-family',
  'font-size',
  'font-size-adjust',
  'font-stretch',
  'font-style',
  'font-variant',
  'font-weight',
  'fx',
  'fy',
  'g1',
  'g2',
  'glyph-name',
  'glyphref',
  'gradientunits',
  'gradienttransform',
  'height',
  'href',
  'id',
  'image-rendering',
  'in',
  'in2',
  'k',
  'k1',
  'k2',
  'k3',
  'k4',
  'kerning',
  'keypoints',
  'keysplines',
  'keytimes',
  'lang',
  'lengthadjust',
  'letter-spacing',
  'kernelmatrix',
  'kernelunitlength',
  'lighting-color',
  'local',
  'marker-end',
  'marker-mid',
  'marker-start',
  'markerheight',
  'markerunits',
  'markerwidth',
  'maskcontentunits',
  'maskunits',
  'max',
  'mask',
  'media',
  'method',
  'mode',
  'min',
  'name',
  'numoctaves',
  'offset',
  'operator',
  'opacity',
  'order',
  'orient',
  'orientation',
  'origin',
  'overflow',
  'paint-order',
  'path',
  'pathlength',
  'patterncontentunits',
  'patterntransform',
  'patternunits',
  'points',
  'preservealpha',
  'preserveaspectratio',
  'primitiveunits',
  'r',
  'rx',
  'ry',
  'radius',
  'refx',
  'refy',
  'repeatcount',
  'repeatdur',
  'restart',
  'result',
  'rotate',
  'scale',
  'seed',
  'shape-rendering',
  'specularconstant',
  'specularexponent',
  'spreadmethod',
  'startoffset',
  'stddeviation',
  'stitchtiles',
  'stop-color',
  'stop-opacity',
  'stroke-dasharray',
  'stroke-dashoffset',
  'stroke-linecap',
  'stroke-linejoin',
  'stroke-miterlimit',
  'stroke-opacity',
  'stroke',
  'stroke-width',
  'style',
  'surfacescale',
  'systemlanguage',
  'tabindex',
  'targetx',
  'targety',
  'transform',
  'transform-origin',
  'text-anchor',
  'text-decoration',
  'text-rendering',
  'textlength',
  'type',
  'u1',
  'u2',
  'unicode',
  'values',
  'viewbox',
  'visibility',
  'version',
  'vert-adv-y',
  'vert-origin-x',
  'vert-origin-y',
  'width',
  'word-spacing',
  'wrap',
  'writing-mode',
  'xchannelselector',
  'ychannelselector',
  'x',
  'x1',
  'x2',
  'xmlns',
  'y',
  'y1',
  'y2',
  'z',
  'zoomandpan'
];

const SVG_ATTRIBUTES_DISALLOW: string[] = [
];

const SVG_ATTRIBUTES = new Set ([
  ...SVG_ATTRIBUTES_ALLOW,
  ...SVG_ATTRIBUTES_DISALLOW
]);

const MATH_ATTRIBUTES_ALLOW = [
  'accent',
  'accentunder',
  'align',
  'bevelled',
  'close',
  'columnsalign',
  'columnlines',
  'columnspan',
  'denomalign',
  'depth',
  'dir',
  'display',
  'displaystyle',
  'encoding',
  'fence',
  'frame',
  'height',
  'href',
  'id',
  'largeop',
  'length',
  'linethickness',
  'lspace',
  'lquote',
  'mathbackground',
  'mathcolor',
  'mathsize',
  'mathvariant',
  'maxsize',
  'minsize',
  'movablelimits',
  'notation',
  'numalign',
  'open',
  'rowalign',
  'rowlines',
  'rowspacing',
  'rowspan',
  'rspace',
  'rquote',
  'scriptlevel',
  'scriptminsize',
  'scriptsizemultiplier',
  'selection',
  'separator',
  'separators',
  'stretchy',
  'subscriptshift',
  'supscriptshift',
  'symmetric',
  'voffset',
  'width',
  'xmlns'
];

const MATH_ATTRIBUTES_DISALLOW: string[] = [
];

const MATH_ATTRIBUTES = new Set ([
  ...MATH_ATTRIBUTES_ALLOW,
  ...MATH_ATTRIBUTES_DISALLOW
]);

/* NAMESPACES */

const NAMESPACES = {
  HTML: 'http://www.w3.org/1999/xhtml',
  SVG: 'http://www.w3.org/2000/svg',
  MATH: 'http://www.w3.org/1998/Math/MathML'
};

const NAMESPACES_ELEMENTS = {
  [NAMESPACES.HTML]: HTML_ELEMENTS,
  [NAMESPACES.SVG]: SVG_ELEMENTS,
  [NAMESPACES.MATH]: MATH_ELEMENTS
};

const NAMESPACES_ATTRIBUTES = {
  [NAMESPACES.HTML]: HTML_ATTRIBUTES,
  [NAMESPACES.SVG]: SVG_ATTRIBUTES,
  [NAMESPACES.MATH]: MATH_ATTRIBUTES
};

const NAMESPACES_ROOTS = {
  [NAMESPACES.HTML]: 'html',
  [NAMESPACES.SVG]: 'svg',
  [NAMESPACES.MATH]: 'math'
};

const NAMESPACES_PREFIXES = {
  [NAMESPACES.HTML]: '',
  [NAMESPACES.SVG]: 'svg:',
  [NAMESPACES.MATH]: 'math:'
};

/* TAG NAMES */

const FUNKY_TAG_NAMES = new Set ([ // Funky elements need special handling
  'A',
  'AREA',
  'BUTTON',
  'FORM',
  'IFRAME',
  'INPUT'
]);

/* OTHERS */

const DEFAULTS = {
  allowComments: true,
  allowCustomElements: false,
  allowUnknownMarkup: false,
  allowElements: [
    ...HTML_ELEMENTS_ALLOW,
    ...SVG_ELEMENTS_ALLOW.map ( name => `svg:${name}` ),
    ...MATH_ELEMENTS_ALLOW.map ( name => `math:${name}` )
  ],
  allowAttributes: mergeMaps ([
    Object.fromEntries ( HTML_ATTRIBUTES_ALLOW.map ( name => [name, ['*']] ) ),
    Object.fromEntries ( SVG_ATTRIBUTES_ALLOW.map ( name => [name, ['svg:*']] ) ),
    Object.fromEntries ( MATH_ATTRIBUTES_ALLOW.map ( name => [name, ['math:*']] ) )
  ])
};

/* EXPORT */

export {HTML_ELEMENTS, SVG_ELEMENTS, MATH_ELEMENTS};
export {HTML_ATTRIBUTES, SVG_ATTRIBUTES, MATH_ATTRIBUTES};
export {NAMESPACES, NAMESPACES_ELEMENTS, NAMESPACES_ATTRIBUTES, NAMESPACES_ROOTS, NAMESPACES_PREFIXES};
export {FUNKY_TAG_NAMES};
export {DEFAULTS};
