import { extend, forin } from '../../utils'

const styles = {}
const camelize = (str) => (str + "").replace(/[_|-]\D/g, (match) => match.charAt(1).toUpperCase())

function camelizify(style) {
    forin(style, (key: string, value: any) => {
        if (key.includes('_') || key.includes('-')) {
            style[camelize(key)] = value
            delete style[key]
        }
    })
    return style
}

function parse(styleString: string) {
    const params = {}
    if (styleString && typeof styleString === 'string') {
        let str = styleString.trim().split(/;|,/)
        for (let i = 0, n = str.length; i < n; i++) {
            if (str[i]) {
                const param = str[i].split(/:|=/)
                params[param[0].trim()] = param[1].replace(/'|"/g, '').trim()
            }
        }
    }
    return params
}

function get(key: string) {
    const type = typeof styles[key]
    if (type === 'string') {
        return parse(styles[key])
    } else if (type === 'object') {
        return styles[key]
    } else {
        return {}
    }
}

function dataify(style, extra) {
    forin(style, (key: string, value: any) => {
        style[key] = replaceValue(value, extra)
    })
    return style
}

export function replaceValue(value: string, extra = {}) {
    if (typeof value === 'string' && value.includes('data.')) {
        const datakey = value.split('data.')[1].trim()
        return extra[datakey]
    } else {
        return value
    }
}

const horAttrs = ['left', 'right', 'centerX']
const verAttrs = ['top', 'bottom', 'centerY']
function extendStyle(style1 = {}, style2 = {}) {
    // 避免同时出现同类布局属性
    // 如 left: 0 / centerX: 0
    Object.keys(style2).map((newKey: string) => {
        [horAttrs, verAttrs].map((attrs) => {
            if (attrs.includes(newKey)) {
                attrs.map((attr) => delete style1[attr])
            }
        })
    })
    extend(true, style1, style2)
    return style1
}

// 合并多个 style
export function mergeStyles(...styleArr: Layout.style[]) {
    return styleArr.reduce((s1, s2) => extendStyle(s1, s2), {})
}

export function getStyle(key: string, pre: '.' | '#' | '' = '') {
    let style = {}
    if (key) { 
        key.trim().split(' ').map((k: string) => {
            extendStyle(style, get(pre + k))
        })
    }
    return style
}

export function addStyle(key: object) {
    if (typeof key === 'object') {
        Object.keys(key).map((cls: string) => {
            styles[cls] = key[cls]
        })
    }
}

function getImportantStyle(tagStyle, clsStyle, idStyle) {
    const styles = [tagStyle, clsStyle, idStyle]
    const importantStyle = {}
    styles.map((style) => {
        forin(style, (key: string, value: any) => {
            if (key.includes('--important')) {
                importantStyle[key.replace('--important', '')] = value
                delete style[key]
            }
        })
    })
    return importantStyle
}

export function createStyle(node: any, extra?) {
    const { name, attrs = {} } = node
    const { style, className, id, class: cls } = attrs
    
    const inlineStyle = parse(style)
    const tagStyle = getStyle(name)
    const clsStyle = getStyle(className || cls, '.')
    const idStyle = getStyle(id, '#')
    const importantStyle = getImportantStyle(tagStyle, clsStyle, idStyle)

    const assignStyle = mergeStyles(tagStyle, clsStyle, idStyle, inlineStyle, importantStyle)

    return dataify(camelizify(assignStyle), extra)
}
