import { getCompletePath } from '.';

let templateStyle:HTMLStyleElement;

function scopedStyleRule (rule:CSSStyleRule, prefix:string, path?:string) {
    const { selectorText, cssText } = rule;
    let str = '';
    
    // 处理选择器
    if(/^((html[\s>~,]+body)|(html|body|:root))$/.test(selectorText)) {
        // 处理顶层选择器，如 body，html 都转换为 micro-app[name=xxx]
        str = cssText.replace(/^((html[\s>~,]+body)|(html|body|:root))/, prefix) + '\n';
    }else {
        // 选择器添加前缀
        str = cssText.replace(/^[\s\S]*{/, cssHead => {
            return cssHead.replace(/(^|,)([^,]+)/g, (_, $1, $2)=>{
                if(/^[\s]*((html|body|:root)|(html[\s>~]+body))/.test($2)) {
                    return `${$1} ${$2.replace(/^[\s]*((html[\s>~]+body)|(html|body|:root))/, prefix)}` + '\n';
                }
                return `${$1} ${prefix} ${$2} \n`;
            });
        });
        
    }

    // 处理样式里的相对地址
    return str.replace(/url\(((".+?")|('.+?')|(.+?))\)/gi, (_, url) => {
        const src = url.replace(/["']/g, '');
        return `url(${getCompletePath(src, path)})`;
    });
}

// 处理媒体查询和样式支持查询
function scopedStyleRuleOther (rule:CSSMediaRule|CSSSupportsRule, prefix:string, packName:string, path?:string) {
    // eslint-disable-next-line no-use-before-define
    const rules = scopedStyleRules(rule.cssRules, prefix, path);
    return `@${packName} ${rule.conditionText} {\n${rules}\n}`;
}

function scopedStyleRules (cssRules:CSSRuleList, prefix:string, path?:string) {
    let rules = '';
    if(cssRules?.length) {
        Array.from(cssRules).forEach((cssRule) => {
            switch (cssRule.type) {
            case 1: // STYLE_RULE
                rules += scopedStyleRule(cssRule as CSSStyleRule, prefix, path) + '\n';
                break;
            case 4: // MEDIA_RULE 媒体查询
                rules += scopedStyleRuleOther(cssRule as CSSMediaRule, prefix, 'media', path) + '\n';
                break;
            case 12: // SUPPORTS_RULE 样式支持
                rules += scopedStyleRuleOther(cssRule as CSSSupportsRule, prefix, 'supports', path) + '\n';
                break;
            default:
                rules += cssRule.cssText;
                break;
            }
        });
        
    }
    return rules;
}

export function scopedCSSTextContent (textContent:string, appName:string, path?:string) {
    const prefix = `mustard-app[name='${appName}'] `; // 样式前缀
    const s = new Date();

    if(!templateStyle) {
        templateStyle = document.createElement('style');
        document.body.appendChild(templateStyle);
        if(templateStyle?.sheet) {
            templateStyle.sheet.disabled = false; // 样式标记不可用
        }
    }

    if(textContent && templateStyle.sheet?.cssRules) {
        templateStyle.textContent = textContent;
        const _textContent = scopedStyleRules(templateStyle.sheet.cssRules, prefix, path);
        templateStyle.textContent = '';
        console.log('============', new Date().getTime() - s.getTime());

        return _textContent;
    }
    return textContent;
}

export function scopedCSS (styleEle:HTMLElement, appName:string, path?:string) {

    styleEle.textContent = scopedCSSTextContent(styleEle.textContent, appName, path);

}


