"use strict"

const _ = require("lodash")

const keywordSets = {}

keywordSets.nonLengthUnits = new Set([
  // Relative length units
  "%",
  // Time length units
  "s",
  "ms",
  // Angle
  "deg",
  "grad",
  "turn",
  "rad",
  // Frequency
  "Hz",
  "kHz",
  // Resolution
  "dpi",
  "dpcm",
  "dppx",
])

keywordSets.lengthUnits = new Set([
  // Relative length units
  "em",
  "ex",
  "ch",
  "rem",
  // Viewport-percentage lengths
  "vh",
  "vw",
  "vmin",
  "vmax",
  "vm",
  // Absolute length units
  "px",
  "mm",
  "cm",
  "in",
  "pt",
  "pc",
  "q",
  // Flexible length units
  "fr",
])

keywordSets.units = uniteSets(keywordSets.nonLengthUnits, keywordSets.lengthUnits)

keywordSets.colorFunctionNames = new Set([
  "rgb",
  "rgba",
  "hsl",
  "hsla",
  "hwb",
  "gray",
])

keywordSets.camelCaseFunctionNames = new Set([
  "translateX",
  "translateY",
  "translateZ",
  "scaleX",
  "scaleY",
  "scaleZ",
  "rotateX",
  "rotateY",
  "rotateZ",
  "skewX",
  "skewY",
])

keywordSets.basicKeywords = new Set([
  "initial",
  "inherit",
  "unset",
])

keywordSets.fontFamilyKeywords = uniteSets(keywordSets.basicKeywords, [
  "serif",
  "sans-serif",
  "cursive",
  "fantasy",
  "monospace",
])

keywordSets.fontWeightRelativeKeywords = new Set([
  "bolder",
  "lighter",
])

keywordSets.fontWeightAbsoluteKeywords = new Set(["bold"])

keywordSets.fontWeightNumericKeywords = new Set([
  "100",
  "200",
  "300",
  "400",
  "500",
  "600",
  "700",
  "800",
  "900",
])

keywordSets.fontWeightKeywords = uniteSets(
  keywordSets.basicKeywords,
  keywordSets.fontWeightRelativeKeywords,
  keywordSets.fontWeightAbsoluteKeywords,
  keywordSets.fontWeightNumericKeywords
)

keywordSets.animationNameKeywords = uniteSets(keywordSets.basicKeywords,
  ["none"]
)

keywordSets.animationTimingFunctionKeywords = uniteSets(keywordSets.basicKeywords, [
  "linear",
  "ease",
  "ease-in",
  "ease-in-out",
  "ease-out",
  "step-start",
  "step-end",
  "steps",
  "cubic-bezier",
])

keywordSets.animationIterationCountKeywords = new Set(["infinite"])

keywordSets.animationDirectionKeywords = uniteSets(keywordSets.basicKeywords, [
  "normal",
  "reverse",
  "alternate",
  "alternate-reverse",
])

keywordSets.animationFillModeKeywords = new Set([
  "none",
  "forwards",
  "backwards",
  "both",
])

keywordSets.animationPlayStateKeywords = uniteSets(keywordSets.basicKeywords, [
  "running",
  "paused",
])

// cf. https://developer.mozilla.org/en-US/docs/Web/CSS/animation
keywordSets.animationShorthandKeywords = uniteSets(
  keywordSets.basicKeywords,
  keywordSets.animationNameKeywords,
  keywordSets.animationTimingFunctionKeywords,
  keywordSets.animationIterationCountKeywords,
  keywordSets.animationDirectionKeywords,
  keywordSets.animationFillModeKeywords,
  keywordSets.animationPlayStateKeywords
)

// These are the ones that can have single-colon notation
keywordSets.levelOneAndTwoPseudoElements = new Set([
  "before",
  "after",
  "first-line",
  "first-letter",
])

// These are the ones that require double-colon notation
keywordSets.levelThreePseudoElements = new Set([
  "before",
  "after",
  "first-line",
  "first-letter",
  "selection",
  "spelling-error",
  "grammar-error",
  "backdrop",
  "marker",
  "placeholder",
  "shadow",
  "slotted",
  "content",
])

keywordSets.pseudoElements = uniteSets(
  keywordSets.levelOneAndTwoPseudoElements,
  keywordSets.levelThreePseudoElements
)

keywordSets.aNPlusBNotationPseudoClasses = new Set([
  "nth-child",
  "nth-column",
  "nth-last-child",
  "nth-last-column",
  "nth-last-of-type",
  "nth-of-type",
])

keywordSets.linguisticPseudoClasses = new Set([
  "dir",
  "lang",
])

keywordSets.otherPseudoClasses = new Set([
  "active",
  "any-link",
  "blank",
  "checked",
  "contains",
  "current",
  "default",
  "disabled",
  "drop",
  "empty",
  "enabled",
  "first-child",
  "first-of-type",
  "focus",
  "focus-within",
  "fullscreen",
  "future",
  "has",
  "host",
  "host-context",
  "hover",
  "indeterminate",
  "in-range",
  "invalid",
  "last-child",
  "last-of-type",
  "link",
  "matches",
  "not",
  "only-child",
  "only-of-type",
  "optional",
  "out-of-range",
  "past",
  "placeholder-shown",
  "read-only",
  "read-write",
  "required",
  "root",
  "scope",
  "target",
  "user-error",
  "user-invalid",
  "val",
  "valid",
  "visited",
])

keywordSets.webkitProprietaryPseudoElements = new Set([
  "scrollbar",
  "scrollbar-button",
  "scrollbar-track",
  "scrollbar-track-piece",
  "scrollbar-thumb",
  "scrollbar-corner",
  "resize",
])

keywordSets.webkitProprietaryPseudoClasses = new Set([
  "horizontal",
  "vertical",
  "decrement",
  "increment",
  "start",
  "end",
  "double-button",
  "single-button",
  "no-button",
  "corner-present",
  "window-inactive",
])

keywordSets.pseudoClasses = uniteSets(
  keywordSets.aNPlusBNotationPseudoClasses,
  keywordSets.linguisticPseudoClasses,
  keywordSets.otherPseudoClasses
)

keywordSets.shorthandTimeProperties = new Set([
  "transition",
  "animation",
])

keywordSets.longhandTimeProperties = new Set([
  "transition-duration",
  "transition-delay",
  "animation-duration",
  "animation-delay",
])

keywordSets.timeProperties = uniteSets(
  keywordSets.shorthandTimeProperties,
  keywordSets.longhandTimeProperties
)

keywordSets.camelCaseKeywords = new Set([
  "optimizeSpeed",
  "optimizeQuality",
  "optimizeLegibility",
  "geometricPrecision",
  "currentColor",
  "crispEdges",
  "visiblePainted",
  "visibleFill",
  "visibleStroke",
  "sRGB",
  "linearRGB",
])

// https://developer.mozilla.org/docs/Web/CSS/counter-increment
keywordSets.counterIncrementKeywords = uniteSets(keywordSets.basicKeywords, ["none"])

keywordSets.gridRowKeywords = uniteSets(keywordSets.basicKeywords, [
  "auto",
  "span",
])

keywordSets.gridColumnKeywords = uniteSets(keywordSets.basicKeywords, [
  "auto",
  "span",
])

keywordSets.gridAreaKeywords = uniteSets(keywordSets.basicKeywords, [
  "auto",
  "span",
])

// https://developer.mozilla.org/ru/docs/Web/CSS/list-style-type
keywordSets.listStyleTypeKeywords = uniteSets(keywordSets.basicKeywords, [
  "none",
  "disc",
  "circle",
  "square",
  "decimal",
  "cjk-decimal",
  "decimal-leading-zero",
  "lower-roman",
  "upper-roman",
  "lower-greek",
  "lower-alpha",
  "lower-latin",
  "upper-alpha",
  "upper-latin",
  "arabic-indic",
  "armenian",
  "bengali",
  "cambodian",
  "cjk-earthly-branch",
  "cjk-ideographic",
  "devanagari",
  "ethiopic-numeric",
  "georgian",
  "gujarati",
  "gurmukhi",
  "hebrew",
  "hiragana",
  "hiragana-iroha",
  "japanese-formal",
  "japanese-informal",
  "kannada",
  "katakana",
  "katakana-iroha",
  "khmer",
  "korean-hangul-formal",
  "korean-hanja-formal",
  "korean-hanja-informal",
  "lao",
  "lower-armenian",
  "malayalam",
  "mongolian",
  "myanmar",
  "oriya",
  "persian",
  "simp-chinese-formal",
  "simp-chinese-informal",
  "tamil",
  "telugu",
  "thai",
  "tibetan",
  "trad-chinese-formal",
  "trad-chinese-informal",
  "upper-armenian",
  "disclosure-open",
  "disclosure-closed",
  // Non-standard extensions (without prefixe)
  "ethiopic-halehame",
  "ethiopic-halehame-am",
  "ethiopic-halehame-ti-er",
  "ethiopic-halehame-ti-et",
  "hangul",
  "hangul-consonant",
  "urdu",
])

keywordSets.listStylePositionKeywords = uniteSets(keywordSets.basicKeywords, [
  "inside",
  "outside",
])

keywordSets.listStyleImageKeywords = uniteSets(keywordSets.basicKeywords, ["none"])

keywordSets.listStyleShorthandKeywords = uniteSets(
  keywordSets.basicKeywords,
  keywordSets.listStyleTypeKeywords,
  keywordSets.listStylePositionKeywords,
  keywordSets.listStyleImageKeywords
)

keywordSets.fontStyleKeywords = uniteSets(keywordSets.basicKeywords, [
  "normal",
  "italic",
  "oblique",
])

keywordSets.fontVariantKeywords = uniteSets(keywordSets.basicKeywords, [
  "normal",
  "none",
  "historical-forms",
  "none",
  "common-ligatures",
  "no-common-ligatures",
  "discretionary-ligatures",
  "no-discretionary-ligatures",
  "historical-ligatures",
  "no-historical-ligatures",
  "contextual",
  "no-contextual",
  "small-caps",
  "small-caps",
  "all-small-caps",
  "petite-caps",
  "all-petite-caps",
  "unicase",
  "titling-caps",
  "lining-nums",
  "oldstyle-nums",
  "proportional-nums",
  "tabular-nums",
  "diagonal-fractions",
  "stacked-fractions",
  "ordinal",
  "slashed-zero",
  "jis78",
  "jis83",
  "jis90",
  "jis04",
  "simplified",
  "traditional",
  "full-width",
  "proportional-width",
  "ruby",
])

keywordSets.fontStretchKeywords = uniteSets(keywordSets.basicKeywords, [
  "semi-condensed",
  "condensed",
  "extra-condensed",
  "ultra-condensed",
  "semi-expanded",
  "expanded",
  "extra-expanded",
  "ultra-expanded",
])

keywordSets.fontSizeKeywords = uniteSets(keywordSets.basicKeywords, [
  "xx-small",
  "x-small",
  "small",
  "medium",
  "large",
  "x-large",
  "xx-large",
  "larger",
  "smaller",
])

keywordSets.lineHeightKeywords = uniteSets(keywordSets.basicKeywords, ["normal"])

keywordSets.fontShorthandKeywords = uniteSets(
  keywordSets.basicKeywords,
  keywordSets.fontStyleKeywords,
  keywordSets.fontVariantKeywords,
  keywordSets.fontWeightKeywords,
  keywordSets.fontStretchKeywords,
  keywordSets.fontSizeKeywords,
  keywordSets.lineHeightKeywords, keywordSets.fontFamilyKeywords
)

keywordSets.keyframeSelectorKeywords = new Set([
  "from",
  "to",
])

// https://developer.mozilla.org/en/docs/Web/CSS/At-rule
keywordSets.atRules = new Set([
  "apply",
  "annotation",
  "character-variant",
  "charset",
  "counter-style",
  "custom-media",
  "custom-selector",
  "document",
  "font-face",
  "font-feature-values",
  "import",
  "keyframes",
  "media",
  "namespace",
  "nest",
  "ornaments",
  "page",
  "styleset",
  "stylistic",
  "supports",
  "swash",
  "viewport",
])

// https://drafts.csswg.org/mediaqueries/#descdef-media-update
keywordSets.deprecatedMediaFeatureNames = new Set([
  "device-aspect-ratio",
  "device-height",
  "device-width",
  "max-device-aspect-ratio",
  "max-device-height",
  "max-device-width",
  "min-device-aspect-ratio",
  "min-device-height",
  "min-device-width",
])

// https://drafts.csswg.org/mediaqueries/#descdef-media-update
keywordSets.mediaFeatureNames = uniteSets(keywordSets.deprecatedMediaFeatureNames, [
  "any-hover",
  "any-pointer",
  "aspect-ratio",
  "color",
  "color-gamut",
  "color-index",
  "grid",
  "height",
  "hover",
  "max-aspect-ratio",
  "max-color",
  "max-color-index",
  "max-height",
  "max-monochrome",
  "max-resolution",
  "max-width",
  "min-aspect-ratio",
  "min-color",
  "min-color-index",
  "min-height",
  "min-monochrome",
  "min-resolution",
  "min-width",
  "monochrome",
  "orientation",
  "overflow-block",
  "overflow-inline",
  "pointer",
  "resolution",
  "scan",
  "scripting",
  "update",
  "width",
])

// https://www.w3.org/TR/CSS22/ui.html#system-colors
keywordSets.systemColors = new Set([
  "activeborder",
  "activecaption",
  "appworkspace",
  "background",
  "buttonface",
  "buttonhighlight",
  "buttonshadow",
  "buttontext",
  "captiontext",
  "graytext",
  "highlight",
  "highlighttext",
  "inactiveborder",
  "inactivecaption",
  "inactivecaptiontext",
  "infobackground",
  "infotext",
  "menu",
  "menutext",
  "scrollbar",
  "threeddarkshadow",
  "threedface",
  "threedhighlight",
  "threedlightshadow",
  "threedshadow",
  "window",
  "windowframe",
  "windowtext",
])

function uniteSets() {
  const sets = Array.from(arguments)

  return new Set(sets.reduce((result, set) => {
    return result.concat(_.toArray(set))
  }, []))
}

module.exports = keywordSets
