import cssEscape from '../shared/utils/css-escape.mjs';
import Layer from '../layer.mjs';
import { VALUE_DELIMITERS, NUMBER_VALUE_REGEX, COLOR_VALUE_REGEX, BORDER_STYLE_VALUES, IMAGE_VALUE_REGEX } from '../common.mjs';
import autofillSolidStyle from '../utils/autofill-solid-style.mjs';

const syntaxes = {
    group: {
        matcher: /^(?:.+?[*_>~+])?\{.+?\}/,
        layer: Layer.Shorthand,
        analyze (className) {
            let i = 0;
            for(; i < className.length; i++){
                if (className[i] === '{' && className[i - 1] !== '\\') {
                    break;
                }
            }
            return [
                className.slice(i),
                className.slice(0, i)
            ];
        },
        declare (value) {
            const declarations = {};
            const addProp = (propertyName)=>{
                const indexOfColon = propertyName.indexOf(':');
                if (indexOfColon !== -1) {
                    const propName = propertyName.slice(0, indexOfColon);
                    declarations[propName] = propertyName.slice(indexOfColon + 1);
                }
            };
            const handleRule = (rule)=>{
                const addProps = (cssText)=>{
                    const cssProperties = cssText.slice(cssEscape(rule.className).length).match(/\{(.*)\}/)?.[1].split(';');
                    if (cssProperties) for (const eachCssProperty of cssProperties){
                        addProp(eachCssProperty);
                    }
                };
                for (const eachNative of rule.natives){
                    addProps(eachNative.text);
                }
                // animation
                if (rule.animationNames) {
                    if (!this.animationNames) {
                        this.animationNames = [];
                    }
                    for (const eachKeyframeName of rule.animationNames){
                        if (!this.animationNames.includes(eachKeyframeName)) {
                            this.animationNames.push(eachKeyframeName);
                        }
                    }
                }
                // variable
                if (rule.variableNames) {
                    if (!this.variableNames) {
                        this.variableNames = [];
                    }
                    for (const eachVariableName of rule.variableNames){
                        if (!this.variableNames.includes(eachVariableName)) {
                            this.variableNames.push(eachVariableName);
                        }
                    }
                }
            };
            const names = [];
            let currentName = '';
            const addName = ()=>{
                if (currentName) {
                    names.push(currentName.replace(/ /g, '|'));
                    currentName = '';
                }
            };
            let i = 1;
            (function analyze(end) {
                for(; i < value.length; i++){
                    const char = value[i];
                    if (!end) {
                        if (char === ';') {
                            addName();
                            continue;
                        }
                        if (char === '}') {
                            break;
                        }
                    }
                    currentName += char;
                    if (end === char) {
                        if (end === '\'' || end === '"') {
                            let count = 0;
                            for(let j = currentName.length - 2;; j--){
                                if (currentName[j] !== '\\') {
                                    break;
                                }
                                count++;
                            }
                            if (count % 2) {
                                continue;
                            }
                        }
                        break;
                    } else if (char in VALUE_DELIMITERS && end !== '\'' && end !== '"') {
                        i++;
                        analyze(VALUE_DELIMITERS[char]);
                    }
                }
            })('');
            addName();
            for (const eachName of names){
                const syntaxes = this.css.generate(eachName);
                if (syntaxes.length) {
                    for (const eachRule of syntaxes){
                        handleRule(eachRule);
                    }
                } else {
                    addProp(eachName);
                }
            }
            return declarations;
        }
    },
    variable: {
        matcher: /^\$[\w-]+:/,
        layer: Layer.Shorthand,
        declare (value) {
            return {
                ['--' + this.keyToken.slice(1, -1)]: value
            };
        }
    },
    'font-size': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'font-weight': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        ambiguousValues: [
            'bolder'
        ],
        layer: Layer.Native
    },
    'font-family': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        layer: Layer.Native
    },
    'font-smoothing': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        ambiguousValues: [
            'antialiased',
            'subpixel-antialiased'
        ],
        layer: Layer.Native,
        declare (value) {
            switch(value){
                case 'subpixel-antialiased':
                    return {
                        '-webkit-font-smoothing': 'auto',
                        '-moz-osx-font-smoothing': 'auto'
                    };
                case 'antialiased':
                    return {
                        '-webkit-font-smoothing': 'antialiased',
                        '-moz-osx-font-smoothing': 'grayscale'
                    };
            }
        }
    },
    'font-style': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        ambiguousValues: [
            'normal',
            'italic',
            'oblique'
        ],
        layer: Layer.Native,
        unit: 'deg'
    },
    'font-variant-numeric': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        ambiguousValues: [
            'ordinal',
            'slashed-zero',
            'lining-nums',
            'oldstyle-nums',
            'proportional-nums',
            'tabular-nums',
            'diagonal-fractions',
            'stacked-fractions'
        ],
        layer: Layer.Native
    },
    'font-variant': {
        ambiguousKeys: [
            'font',
            'f'
        ],
        layer: Layer.NativeShorthand
    },
    font: {
        subkey: 'f',
        layer: Layer.NativeShorthand,
        variables: [
            'font-family',
            'font-variant',
            'font-weight',
            'font-size',
            'font-style',
            'line-height'
        ]
    },
    'font-feature-settings': {
        key: 'font-feature',
        layer: Layer.Native
    },
    color: {
        key: 'fg',
        layer: Layer.Native,
        variables: [
            'text'
        ]
    },
    // margin
    'margin-left': {
        key: 'ml',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'margin-right': {
        key: 'mr',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'margin-top': {
        key: 'mt',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'margin-bottom': {
        key: 'mb',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'margin-x': {
        key: 'mx',
        subkey: 'margin-x',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'margin-left': value,
                'margin-right': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    'margin-y': {
        key: 'my',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'margin-top': value,
                'margin-bottom': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    margin: {
        key: 'm',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    // margin inline
    'margin-inline-start': {
        key: 'mis',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'margin-inline-end': {
        key: 'mie',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'margin-inline': {
        key: 'mi',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    // padding
    'padding-left': {
        key: 'pl',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'padding-right': {
        key: 'pr',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'padding-top': {
        key: 'pt',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'padding-bottom': {
        key: 'pb',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'padding-x': {
        key: 'px',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'padding-left': value,
                'padding-right': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    'padding-y': {
        key: 'py',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'padding-top': value,
                'padding-bottom': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    padding: {
        key: 'p',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    // padding inline
    'padding-inline-start': {
        key: 'pis',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'padding-inline-end': {
        key: 'pie',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'padding-inline': {
        key: 'pi',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    // flex
    'flex-basis': {
        ambiguousKeys: [
            'flex'
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'flex-wrap': {
        ambiguousKeys: [
            'flex'
        ],
        ambiguousValues: [
            'wrap',
            'nowrap',
            'wrap-reverse'
        ],
        layer: Layer.Native
    },
    'flex-grow': {
        ambiguousKeys: [
            'flex'
        ],
        layer: Layer.Native
    },
    'flex-shrink': {
        ambiguousKeys: [
            'flex'
        ],
        layer: Layer.Native
    },
    'flex-direction': {
        ambiguousKeys: [
            'flex'
        ],
        ambiguousValues: [
            'row',
            'row-reverse',
            'column',
            'column-reverse'
        ],
        layer: Layer.Native
    },
    flex: {
        layer: Layer.NativeShorthand
    },
    display: {
        key: 'd',
        layer: Layer.Native
    },
    width: {
        key: 'w',
        unit: 'rem',
        layer: Layer.Native
    },
    height: {
        key: 'h',
        unit: 'rem',
        layer: Layer.Native
    },
    'min-width': {
        key: 'min-w',
        unit: 'rem',
        layer: Layer.Native
    },
    'min-height': {
        key: 'min-h',
        unit: 'rem',
        layer: Layer.Native
    },
    size: {
        layer: Layer.Shorthand,
        unit: 'rem',
        declare (_value, valueComponents) {
            const length = valueComponents.length;
            return {
                width: length === 1 ? valueComponents[0].text : valueComponents[0].text,
                height: length === 1 ? valueComponents[0].text : valueComponents[2].text
            };
        }
    },
    'min-size': {
        key: 'min',
        layer: Layer.Shorthand,
        unit: 'rem',
        declare (_value, valueComponents) {
            const length = valueComponents.length;
            return {
                'min-width': length === 1 ? valueComponents[0].text : valueComponents[0].text,
                'min-height': length === 1 ? valueComponents[0].text : valueComponents[2].text
            };
        }
    },
    'max-size': {
        key: 'max',
        layer: Layer.Shorthand,
        unit: 'rem',
        declare (_value, valueComponents) {
            const length = valueComponents.length;
            return {
                'max-width': length === 1 ? valueComponents[0].text : valueComponents[0].text,
                'max-height': length === 1 ? valueComponents[0].text : valueComponents[2].text
            };
        }
    },
    'box-sizing': {
        ambiguousKeys: [
            'box'
        ],
        layer: Layer.Native
    },
    'box-decoration-break': {
        key: 'box-decoration',
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-box-decoration-break': value,
                'box-decoration-break': value
            };
        }
    },
    contain: {
        layer: Layer.Native
    },
    content: {
        layer: Layer.Native
    },
    'counter-increment': {
        layer: Layer.Native
    },
    'counter-reset': {
        layer: Layer.Native
    },
    'letter-spacing': {
        key: 'tracking',
        subkey: 'ls',
        layer: Layer.Native,
        unit: 'em'
    },
    'line-height': {
        key: 'leading',
        subkey: 'line-h',
        layer: Layer.Native
    },
    'object-fit': {
        ambiguousKeys: [
            'object',
            'obj'
        ],
        ambiguousValues: [
            'contain',
            'cover',
            'fill',
            'scale-down'
        ],
        layer: Layer.Native
    },
    'object-position': {
        ambiguousKeys: [
            'object',
            'obj'
        ],
        ambiguousValues: [
            'top',
            'bottom',
            'right',
            'left',
            'center'
        ],
        layer: Layer.Native
    },
    'text-align': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'justify',
            'center',
            'left',
            'right',
            'start',
            'end'
        ],
        layer: Layer.Native
    },
    'text-decoration-color': {
        ambiguousKeys: [
            'text-decoration'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'text'
        ]
    },
    'text-decoration-style': {
        ambiguousKeys: [
            'text-decoration'
        ],
        ambiguousValues: [
            'solid',
            'double',
            'dotted',
            'dashed',
            'wavy'
        ],
        layer: Layer.Native
    },
    'text-decoration-thickness': {
        ambiguousKeys: [
            'text-decoration'
        ],
        ambiguousValues: [
            'from-font',
            NUMBER_VALUE_REGEX
        ],
        layer: Layer.Native,
        unit: 'em'
    },
    'text-decoration-line': {
        ambiguousKeys: [
            'text-decoration'
        ],
        ambiguousValues: [
            'underline',
            'overline',
            'line-through'
        ],
        layer: Layer.Native
    },
    'text-decoration': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'underline',
            'overline',
            'line-through'
        ],
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'text'
        ],
        declare (value) {
            return {
                '-webkit-text-decoration': value,
                'text-decoration': value
            };
        }
    },
    'text-underline-offset': {
        ambiguousKeys: [
            'text-underline'
        ],
        unit: 'rem',
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    'text-underline-position': {
        ambiguousKeys: [
            'text-underline'
        ],
        ambiguousValues: [
            'front-font',
            'under',
            'left',
            'right'
        ],
        layer: Layer.Native
    },
    'text-overflow': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'ellipsis',
            'clip'
        ],
        layer: Layer.Native
    },
    'text-orientation': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'mixed',
            'upright',
            'sideways-right',
            'sideways',
            'use-glyph-orientation'
        ],
        layer: Layer.Native
    },
    'text-transform': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'uppercase',
            'lowercase',
            'capitalize'
        ],
        layer: Layer.Native
    },
    'text-rendering': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'optimizeSpeed',
            'optimizeLegibility',
            'geometricPrecision'
        ],
        layer: Layer.Native
    },
    'text-wrap': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            'wrap',
            'nowrap',
            'balance',
            'pretty'
        ],
        layer: Layer.NativeShorthand
    },
    'text-indent': {
        unit: 'rem',
        layer: Layer.Native
    },
    'vertical-align': {
        key: 'v',
        subkey: 'vertical',
        layer: Layer.Native
    },
    columns: {
        key: 'cols',
        layer: Layer.NativeShorthand
    },
    'white-space': {
        layer: Layer.Native
    },
    top: {
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    bottom: {
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    left: {
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    right: {
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    inset: {
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    'max-height': {
        key: 'max-h',
        unit: 'rem',
        layer: Layer.Native
    },
    'max-width': {
        key: 'max-w',
        unit: 'rem',
        layer: Layer.Native
    },
    opacity: {
        layer: Layer.Native
    },
    visibility: {
        layer: Layer.Native
    },
    clear: {
        layer: Layer.Native
    },
    float: {
        layer: Layer.Native
    },
    isolation: {
        layer: Layer.Native
    },
    'overflow-x': {
        layer: Layer.Native,
        declare (value) {
            return value === 'overlay' ? {
                'overflow-x': [
                    'auto',
                    value
                ]
            } : {
                'overflow-x': value
            };
        }
    },
    'overflow-y': {
        layer: Layer.Native,
        declare (value) {
            return value === 'overlay' ? {
                'overflow-y': [
                    'auto',
                    value
                ]
            } : {
                'overflow-y': value
            };
        }
    },
    overflow: {
        layer: Layer.NativeShorthand,
        declare (value) {
            return value === 'overlay' ? {
                overflow: [
                    'auto',
                    value
                ]
            } : {
                overflow: value
            };
        }
    },
    'overscroll-behavior-x': {
        layer: Layer.Native
    },
    'overscroll-behavior-y': {
        layer: Layer.Native
    },
    'overscroll-behavior': {
        layer: Layer.NativeShorthand
    },
    'z-index': {
        key: 'z',
        layer: Layer.Native
    },
    position: {
        layer: Layer.Native
    },
    cursor: {
        layer: Layer.Native
    },
    'pointer-events': {
        layer: Layer.Native
    },
    resize: {
        layer: Layer.Native
    },
    'touch-action': {
        layer: Layer.Native
    },
    'word-break': {
        layer: Layer.Native
    },
    'word-spacing': {
        layer: Layer.Native,
        unit: 'em'
    },
    'user-drag': {
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-user-drag': value,
                'user-drag': value
            };
        }
    },
    'user-select': {
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-user-select': value,
                'user-select': value
            };
        }
    },
    'text-shadow': {
        unit: 'rem',
        layer: Layer.Native
    },
    'text-size': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        declare (value) {
            const diff = .875;
            return {
                'font-size': value,
                'line-height': `calc(${value} + ${diff}em)`
            };
        },
        layer: Layer.Shorthand
    },
    'text-fill-color': {
        ambiguousKeys: [
            'text',
            't'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'text'
        ],
        declare (value) {
            return {
                '-webkit-text-fill-color': value
            };
        }
    },
    'text-stroke-width': {
        ambiguousKeys: [
            'text-stroke'
        ],
        ambiguousValues: [
            'thin',
            'medium',
            'thick',
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-text-stroke-width': value
            };
        }
    },
    'text-stroke-color': {
        ambiguousKeys: [
            'text-stroke'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-text-stroke-color': value
            };
        }
    },
    'text-stroke': {
        unit: 'rem',
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-text-stroke': value
            };
        }
    },
    'text-truncate': {
        subkey: 'lines',
        declare (value) {
            return {
                display: '-webkit-box',
                '-webkit-box-orient': 'vertical',
                '-webkit-line-clamp': value,
                overflow: 'hidden',
                'overflow-wrap': 'break-word',
                'text-overflow': 'ellipsis'
            };
        },
        layer: Layer.Shorthand
    },
    'box-shadow': {
        key: 'shadow',
        subkey: 's',
        unit: 'rem',
        layer: Layer.Native
    },
    'table-layout': {
        layer: Layer.Native
    },
    'transform-box': {
        ambiguousKeys: [
            'transform'
        ],
        layer: Layer.Native
    },
    'transform-style': {
        ambiguousKeys: [
            'transform'
        ],
        ambiguousValues: [
            'flat',
            'preserve-3d'
        ],
        layer: Layer.Native
    },
    'transform-origin': {
        ambiguousKeys: [
            'transform'
        ],
        ambiguousValues: [
            'top',
            'bottom',
            'right',
            'left',
            'center',
            NUMBER_VALUE_REGEX
        ],
        unit: 'px',
        layer: Layer.Native
    },
    transform: {
        matcher: /^(?:translate|scale|skew|rotate|perspective|matrix)(?:3d|[XYZ])?\(/,
        layer: Layer.Native,
        analyze (className) {
            return [
                className.startsWith('transform') ? className.slice(10) : className
            ];
        },
        unit: 'px',
        variables: [
            'spacing'
        ]
    },
    'transition-property': {
        key: '~property',
        layer: Layer.Native
    },
    'transition-timing-function': {
        key: '~easing',
        layer: Layer.Native
    },
    'transition-duration': {
        key: '~duration',
        layer: Layer.Native,
        unit: 'ms'
    },
    'transition-delay': {
        key: '~delay',
        layer: Layer.Native,
        unit: 'ms'
    },
    transition: {
        sign: '~',
        analyze (className) {
            if (className.startsWith('~')) {
                return [
                    className.slice(1)
                ];
            } else {
                const indexOfColon = className.indexOf(':');
                this.keyToken = className.slice(0, indexOfColon + 1);
                return [
                    className.slice(indexOfColon + 1)
                ];
            }
        },
        layer: Layer.NativeShorthand
    },
    'animation-delay': {
        key: '@delay',
        layer: Layer.Native,
        unit: 'ms'
    },
    'animation-direction': {
        key: '@direction',
        layer: Layer.Native
    },
    'animation-duration': {
        key: '@duration',
        layer: Layer.Native,
        unit: 'ms'
    },
    'animation-fill-mode': {
        key: '@fill',
        layer: Layer.Native
    },
    'animation-iteration-count': {
        key: '@iteration',
        layer: Layer.Native
    },
    'animation-name': {
        key: '@name',
        layer: Layer.Native,
        includeAnimations: true
    },
    'animation-play-state': {
        key: '@play',
        layer: Layer.Native
    },
    'animation-timing-function': {
        key: '@easing',
        layer: Layer.Native
    },
    animation: {
        sign: '@',
        layer: Layer.NativeShorthand,
        includeAnimations: true,
        analyze (className) {
            if (className.startsWith('@')) {
                return [
                    className.slice(1)
                ];
            } else {
                const indexOfColon = className.indexOf(':');
                this.keyToken = className.slice(0, indexOfColon + 1);
                return [
                    className.slice(indexOfColon + 1)
                ];
            }
        }
    },
    'border-collapse': {
        ambiguousKeys: [
            'b',
            'border'
        ],
        ambiguousValues: [
            'collapse',
            'separate'
        ],
        layer: Layer.Native
    },
    'border-spacing': {
        unit: 'rem',
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    // border color
    'border-top-color': {
        ambiguousKeys: [
            'bt',
            'border-top'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'frame'
        ]
    },
    'border-bottom-color': {
        ambiguousKeys: [
            'bb',
            'border-bottom'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'frame'
        ]
    },
    'border-left-color': {
        ambiguousKeys: [
            'bl',
            'border-left'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'frame'
        ]
    },
    'border-right-color': {
        ambiguousKeys: [
            'br',
            'border-right'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'frame'
        ]
    },
    'border-x-color': {
        ambiguousKeys: [
            'bx',
            'border-x'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Shorthand,
        variables: [
            'frame'
        ],
        declare (value) {
            return {
                'border-left-color': value,
                'border-right-color': value
            };
        }
    },
    'border-y-color': {
        ambiguousKeys: [
            'by',
            'border-y'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Shorthand,
        variables: [
            'frame'
        ],
        declare (value) {
            return {
                'border-top-color': value,
                'border-bottom-color': value
            };
        }
    },
    'border-color': {
        ambiguousKeys: [
            'b',
            'border'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.NativeShorthand,
        variables: [
            'frame'
        ]
    },
    // border radius
    'border-top-left-radius': {
        key: 'rtl',
        unit: 'rem',
        layer: Layer.Native
    },
    'border-top-right-radius': {
        key: 'rtr',
        unit: 'rem',
        layer: Layer.Native
    },
    'border-bottom-left-radius': {
        key: 'rbl',
        unit: 'rem',
        layer: Layer.Native
    },
    'border-bottom-right-radius': {
        key: 'rbr',
        unit: 'rem',
        layer: Layer.Native
    },
    'border-top-radius': {
        key: 'rt',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-top-left-radius': value,
                'border-top-right-radius': value
            };
        }
    },
    'border-bottom-radius': {
        key: 'rb',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-bottom-left-radius': value,
                'border-bottom-right-radius': value
            };
        }
    },
    'border-left-radius': {
        key: 'rl',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-top-left-radius': value,
                'border-bottom-left-radius': value
            };
        }
    },
    'border-right-radius': {
        key: 'rr',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-top-right-radius': value,
                'border-bottom-right-radius': value
            };
        }
    },
    'border-radius': {
        key: 'r',
        unit: 'rem',
        layer: Layer.NativeShorthand
    },
    // border style
    'border-top-style': {
        ambiguousKeys: [
            'bt',
            'border-top'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Native
    },
    'border-bottom-style': {
        ambiguousKeys: [
            'bb',
            'border-bottom'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Native
    },
    'border-left-style': {
        ambiguousKeys: [
            'bl',
            'border-left'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Native
    },
    'border-right-style': {
        ambiguousKeys: [
            'br',
            'border-right'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Native
    },
    'border-x-style': {
        ambiguousKeys: [
            'bx',
            'border-x'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-left-style': value,
                'border-right-style': value
            };
        }
    },
    'border-y-style': {
        ambiguousKeys: [
            'by',
            'border-y'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-top-style': value,
                'border-bottom-style': value
            };
        }
    },
    'border-style': {
        ambiguousKeys: [
            'b',
            'border'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.NativeShorthand
    },
    // border width
    'border-top-width': {
        ambiguousKeys: [
            'bt',
            'border-top'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'border-bottom-width': {
        ambiguousKeys: [
            'bb',
            'border-bottom'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'border-left-width': {
        ambiguousKeys: [
            'bl',
            'border-left'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'border-right-width': {
        ambiguousKeys: [
            'br',
            'border-right'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'border-x-width': {
        ambiguousKeys: [
            'bx',
            'border-x'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-left-width': value,
                'border-right-width': value
            };
        }
    },
    'border-y-width': {
        ambiguousKeys: [
            'by',
            'border-y'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'border-top-width': value,
                'border-bottom-width': value
            };
        }
    },
    'border-width': {
        ambiguousKeys: [
            'b',
            'border'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.NativeShorthand
    },
    // border image
    'border-image-repeat': {
        ambiguousKeys: [
            'border-image'
        ],
        ambiguousValues: [
            'stretch',
            'repeat',
            'round',
            'space'
        ],
        layer: Layer.Native
    },
    'border-image-slice': {
        ambiguousKeys: [
            'border-image'
        ],
        layer: Layer.Native
    },
    'border-image-source': {
        ambiguousKeys: [
            'border-image'
        ],
        ambiguousValues: [
            IMAGE_VALUE_REGEX
        ],
        layer: Layer.Native
    },
    'border-image-width': {
        ambiguousKeys: [
            'border-image'
        ],
        ambiguousValues: [
            'auto',
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'border-image-outset': {
        ambiguousKeys: [
            'border-image'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'border-image': {
        layer: Layer.NativeShorthand
    },
    // border
    'border-top': {
        key: 'bt',
        layer: Layer.NativeShorthand,
        unit: 'rem',
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ]
    },
    'border-bottom': {
        key: 'bb',
        layer: Layer.NativeShorthand,
        unit: 'rem',
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ]
    },
    'border-left': {
        key: 'bl',
        layer: Layer.NativeShorthand,
        unit: 'rem',
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ]
    },
    'border-right': {
        key: 'br',
        layer: Layer.NativeShorthand,
        unit: 'rem',
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ]
    },
    'border-x': {
        key: 'bx',
        unit: 'rem',
        layer: Layer.Shorthand,
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ],
        declare (value) {
            return {
                'border-left': value,
                'border-right': value
            };
        }
    },
    'border-y': {
        key: 'by',
        unit: 'rem',
        layer: Layer.Shorthand,
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ],
        declare (value) {
            return {
                'border-top': value,
                'border-bottom': value
            };
        }
    },
    border: {
        key: 'b',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        transformValueComponents: autofillSolidStyle,
        variables: [
            'frame'
        ]
    },
    'background-attachment': {
        ambiguousKeys: [
            'bg'
        ],
        ambiguousValues: [
            'fixed',
            'local',
            'scroll'
        ],
        layer: Layer.Native
    },
    'background-blend-mode': {
        key: 'bg-blend',
        layer: Layer.Native
    },
    'background-color': {
        ambiguousKeys: [
            'bg'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native
    },
    'background-clip': {
        key: 'bg-clip',
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-background-clip': value,
                'background-clip': value
            };
        }
    },
    'background-origin': {
        key: 'bg-origin',
        layer: Layer.Native
    },
    'background-position': {
        ambiguousKeys: [
            'bg'
        ],
        ambiguousValues: [
            'top',
            'bottom',
            'right',
            'left',
            'center'
        ],
        layer: Layer.Native,
        unit: 'px'
    },
    'background-repeat': {
        ambiguousKeys: [
            'bg'
        ],
        ambiguousValues: [
            'space',
            'round',
            'repeat',
            'no-repeat',
            'repeat-x',
            'repeat-y'
        ],
        layer: Layer.Native
    },
    'background-size': {
        ambiguousKeys: [
            'bg'
        ],
        ambiguousValues: [
            'auto',
            'cover',
            'contain',
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    'background-image': {
        ambiguousKeys: [
            'bg'
        ],
        ambiguousValues: [
            IMAGE_VALUE_REGEX
        ],
        layer: Layer.Native
    },
    background: {
        key: 'bg',
        layer: Layer.NativeShorthand
    },
    gradient: {
        matcher: /^gradient\(/,
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'background-image': 'linear-' + value
            };
        }
    },
    'mix-blend-mode': {
        key: 'blend',
        layer: Layer.Native
    },
    'backdrop-filter': {
        key: 'bd',
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-backdrop-filter': value,
                'backdrop-filter': value
            };
        }
    },
    filter: {
        matcher: /^(?:blur|brightness|contrast|drop-shadow|grayscale|hue-rotate|invert|opacity|saturate|sepia)\(/,
        layer: Layer.Native
    },
    fill: {
        layer: Layer.Native
    },
    'stroke-dasharray': {
        layer: Layer.Native
    },
    'stroke-dashoffset': {
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    'stroke-width': {
        ambiguousKeys: [
            'stroke'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        layer: Layer.Native
    },
    stroke: {
        layer: Layer.Native
    },
    x: {
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    y: {
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    cx: {
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    cy: {
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    rx: {
        layer: Layer.Native
    },
    ry: {
        layer: Layer.Native
    },
    'grid-column-start': {
        key: 'grid-col-start',
        layer: Layer.Native
    },
    'grid-column-end': {
        key: 'grid-col-end',
        layer: Layer.Native
    },
    'grid-column-span': {
        key: 'grid-col-span',
        layer: Layer.Shorthand,
        transformValue (value) {
            return 'span' + ' ' + value + '/' + 'span' + ' ' + value;
        },
        declare (value) {
            return {
                'grid-column': value
            };
        }
    },
    'grid-column': {
        key: 'grid-col',
        layer: Layer.NativeShorthand
    },
    'grid-columns': {
        key: 'grid-cols',
        declare (value) {
            return {
                display: 'grid',
                'grid-template-columns': 'repeat' + '(' + value + ',' + 'minmax' + '(' + 0 + ',' + 1 + 'fr' + '))'
            };
        },
        layer: Layer.Shorthand
    },
    'grid-row-start': {
        layer: Layer.Native
    },
    'grid-row-end': {
        layer: Layer.Native
    },
    'grid-row-span': {
        layer: Layer.Shorthand,
        transformValue (value) {
            return 'span' + ' ' + value + '/' + 'span' + ' ' + value;
        },
        declare (value) {
            return {
                'grid-row': value
            };
        }
    },
    'grid-row': {
        layer: Layer.NativeShorthand
    },
    'grid-rows': {
        declare (value) {
            return {
                display: 'grid',
                'grid-auto-flow': 'column',
                'grid-template-rows': 'repeat' + '(' + value + ',' + 'minmax' + '(' + 0 + ',' + 1 + 'fr' + '))'
            };
        },
        layer: Layer.Shorthand
    },
    'grid-auto-columns': {
        key: 'grid-auto-cols',
        layer: Layer.Native
    },
    'grid-auto-flow': {
        key: 'grid-flow',
        layer: Layer.Native
    },
    'grid-auto-rows': {
        layer: Layer.Native
    },
    'grid-template-areas': {
        layer: Layer.Native
    },
    'grid-template-columns': {
        key: 'grid-template-cols',
        layer: Layer.Native,
        unit: 'rem'
    },
    'grid-template-rows': {
        layer: Layer.Native,
        unit: 'rem'
    },
    'grid-template': {
        layer: Layer.NativeShorthand
    },
    'grid-area': {
        layer: Layer.NativeShorthand
    },
    grid: {
        layer: Layer.NativeShorthand
    },
    'column-gap': {
        key: 'gap-x',
        unit: 'rem',
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    'row-gap': {
        key: 'gap-y',
        unit: 'rem',
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    gap: {
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    order: {
        key: 'o',
        layer: Layer.Native
    },
    'break-inside': {
        layer: Layer.Native
    },
    'break-before': {
        layer: Layer.Native
    },
    'break-after': {
        layer: Layer.Native
    },
    'aspect-ratio': {
        key: 'aspect',
        layer: Layer.Native
    },
    'column-span': {
        key: 'col-span',
        layer: Layer.Native
    },
    'align-content': {
        subkey: 'ac',
        layer: Layer.Native
    },
    'align-items': {
        subkey: 'ai',
        layer: Layer.Native
    },
    'align-self': {
        subkey: 'as',
        layer: Layer.Native
    },
    'justify-content': {
        subkey: 'jc',
        layer: Layer.Native
    },
    'justify-items': {
        subkey: 'ji',
        layer: Layer.Native
    },
    'justify-self': {
        subkey: 'js',
        layer: Layer.Native
    },
    'place-content': {
        layer: Layer.NativeShorthand
    },
    'place-items': {
        layer: Layer.NativeShorthand
    },
    'place-self': {
        layer: Layer.NativeShorthand
    },
    'list-style-position': {
        ambiguousKeys: [
            'list-style'
        ],
        ambiguousValues: [
            'inside',
            'outside'
        ],
        layer: Layer.Native
    },
    'list-style-type': {
        ambiguousKeys: [
            'list-style'
        ],
        ambiguousValues: [
            'disc',
            'decimal'
        ],
        layer: Layer.Native
    },
    'list-style-image': {
        ambiguousKeys: [
            'list-style'
        ],
        ambiguousValues: [
            IMAGE_VALUE_REGEX
        ],
        layer: Layer.Native
    },
    'list-style': {
        layer: Layer.NativeShorthand
    },
    'outline-color': {
        ambiguousKeys: [
            'outline'
        ],
        ambiguousValues: [
            COLOR_VALUE_REGEX
        ],
        layer: Layer.Native,
        variables: [
            'frame'
        ]
    },
    'outline-offset': {
        unit: 'rem',
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    'outline-style': {
        ambiguousKeys: [
            'outline'
        ],
        ambiguousValues: BORDER_STYLE_VALUES,
        layer: Layer.Native
    },
    'outline-width': {
        ambiguousKeys: [
            'outline'
        ],
        ambiguousValues: [
            'medium',
            'thick',
            'thin',
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native
    },
    outline: {
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'outline-width',
            'outline-style',
            'outline-offset',
            'outline-color',
            'frame'
        ],
        transformValueComponents: autofillSolidStyle
    },
    'accent-color': {
        key: 'accent',
        layer: Layer.Native
    },
    appearance: {
        layer: Layer.Native
    },
    'caret-color': {
        key: 'caret',
        layer: Layer.Native,
        variables: [
            'text'
        ]
    },
    'scroll-behavior': {
        layer: Layer.Native
    },
    // scroll margin
    'scroll-margin-left': {
        key: 'scroll-ml',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-margin-right': {
        key: 'scroll-mr',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-margin-top': {
        key: 'scroll-mt',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-margin-bottom': {
        key: 'scroll-mb',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-margin-x': {
        key: 'scroll-mx',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'scroll-margin-left': value,
                'scroll-margin-right': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    'scroll-margin-y': {
        key: 'scroll-my',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'scroll-margin-top': value,
                'scroll-margin-bottom': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    'scroll-margin': {
        key: 'scroll-m',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    // scroll padding
    'scroll-padding-left': {
        key: 'scroll-pl',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-padding-right': {
        key: 'scroll-pr',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-padding-top': {
        key: 'scroll-pt',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-padding-bottom': {
        key: 'scroll-pb',
        layer: Layer.Native,
        unit: 'rem',
        variables: [
            'spacing'
        ]
    },
    'scroll-padding-x': {
        key: 'scroll-px',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'scroll-padding-left': value,
                'scroll-padding-right': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    'scroll-padding-y': {
        key: 'scroll-py',
        unit: 'rem',
        layer: Layer.Shorthand,
        declare (value) {
            return {
                'scroll-padding-top': value,
                'scroll-padding-bottom': value
            };
        },
        variables: [
            'spacing'
        ]
    },
    'scroll-padding': {
        key: 'scroll-p',
        unit: 'rem',
        layer: Layer.NativeShorthand,
        variables: [
            'spacing'
        ]
    },
    // scroll snap
    'scroll-snap-align': {
        ambiguousKeys: [
            'scroll-snap'
        ],
        ambiguousValues: [
            'start',
            'end',
            'center'
        ],
        layer: Layer.Native
    },
    'scroll-snap-stop': {
        ambiguousKeys: [
            'scroll-snap'
        ],
        ambiguousValues: [
            'normal',
            'always'
        ],
        layer: Layer.Native
    },
    'scroll-snap-type': {
        ambiguousKeys: [
            'scroll-snap'
        ],
        ambiguousValues: [
            'x',
            'y',
            'block',
            'inline',
            'both'
        ],
        layer: Layer.Native
    },
    'will-change': {
        layer: Layer.Native
    },
    'writing-mode': {
        key: 'writing',
        layer: Layer.Native
    },
    direction: {
        layer: Layer.Native
    },
    'shape-outside': {
        ambiguousKeys: [
            'shape'
        ],
        ambiguousValues: [
            /(?:inset|circle|ellipse|polygon|url|linear-gradient)\(.*\)/
        ],
        layer: Layer.Native
    },
    'shape-margin': {
        ambiguousKeys: [
            'shape'
        ],
        ambiguousValues: [
            NUMBER_VALUE_REGEX
        ],
        unit: 'rem',
        layer: Layer.Native,
        variables: [
            'spacing'
        ]
    },
    'shape-image-threshold': {
        layer: Layer.Native
    },
    'clip-path': {
        key: 'clip',
        layer: Layer.Native
    },
    quotes: {
        layer: Layer.Native
    },
    'mask-image': {
        layer: Layer.Native,
        declare (value) {
            return {
                '-webkit-mask-image': value,
                'mask-image': value
            };
        }
    }
};

export { syntaxes as default };
