import { extend } from './extend'

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 forin(object: object, fn: (key?: string, value?: any) => void) {
    if (typeof object === 'object') {
        for (const key in object) {
            if (object.hasOwnProperty(key)) {
                const value = object[key]
                fn(key, value)
            }
        }
    }
}

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 getStyle(key: string) {
    const type = typeof styles[key]
    if (type === 'string') {
        return parse(styles[key])
    } else if (type === 'object') {
        return styles[key]
    } else {
        return {}
    }
}

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

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
    }
}

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

export function createStyle(node: any, extra) {
    const { name, attrs = {} } = node
    const { style, className, id, class: cls } = attrs
    
    const inlineStyle = parse(style)
    const tagStyle = get(name)
    const clsStyle = get(className || cls, '.')
    const idStyle = get(id, '#')
    const assignStyle = extend(true, tagStyle, clsStyle, idStyle, inlineStyle)

    if (typeof assignStyle.backgroundFrame === 'string') {
        assignStyle.backgroundFrame = assignStyle.backgroundFrame.split(/\s/)
    }

    return dataify(camelizify(assignStyle), extra)
}
