import { Sprite, AnimatedSprite, Text, Rect, Circle, View } from '../comp'
import { createStyle, addStyle, replaceValue } from '../style'
import { getValue, error, extend, warn } from '../../utils'
import classSystem from '../class'
import attrSystem from '../attrs'
import { parse } from './parser'

/*
* 模板解析系统
* 解析标签模板，并绘制到画布上
*/
function createNode(node: any, extra?: any) {
    let element: any = null
    if (node.type === 'tag') {
        const _style = createStyle(node, extra)
        const image = replaceValue(getValue(node, 'attrs.src'), extra)

        switch (node.name.toLowerCase()) {
            case 'sprite':
            case 'image':
                element = Sprite(image, _style)
                break
            case 'animated-sprite':
            case 'animated-image':
            case 'animatedsprite':
            case 'animatedimage':
                element = AnimatedSprite(image, _style)
                break
            case 'text':
            case 'txt':
                if (node.children.length) {
                    let content = ''
                    node.children.map((child) => {
                        if (child.type === 'text') {
                            content += child.content
                        }
                    })
                    element = Text(content, _style)
                } else {
                    warn(`the <text> must have content`)
                }
                break
            case 'view':
            case 'div':
                element = View(_style)
                break
            case 'rect':
            case 'rectangle':
                element = Rect(_style)
                break
            case 'circle': 
                element = Circle(_style)
                break
        }
    } else if (node.type === 'text' && node.content.trim()) {
        element = Text(node.content.trim())
        element['isAutoText'] = true
    }

    extend(true, element, { ...attrSystem, ...classSystem }, { node, ...node.attrs })
    return element
}

function addChild(rootTag, root, extra?: any) {
    // text 标签中的子元素不渲染
    if (root.type !== 'text' && getValue(rootTag, 'children.length')) {
        rootTag.children.map((childTag) => {
            const child = createNode(childTag, extra)
            if (child) {
                addChild(childTag, child)
                child.appendTo(root, false)
            }
        })
    }
}

/**
 * 接受样式数据
 * @param { Temp.styleObj } styles - 样式数据
 */
export function style(styles: Temp.styleObj) {
    addStyle(styles)
}

/**
 * 模板渲染函数
 * @param { string } template - 字符串标签模板
 * @param { any } mountedRoot - 渲染到的根节点
 * @param { Temp.extra } extra - 携带数据，用于向模板中传递数据
 */
export function render(template: string, mountedRoot: any, extra?: Temp.extra) {
    if (typeof template === 'string') {
        const ast = parse(template)
        if (ast && ast.length) {
            const root: any[] = []
            ast.map((astNode) => {
                const node = createNode(astNode, extra)
                // 构建节点树
                addChild(astNode, node, extra)
                
                if (mountedRoot && mountedRoot.addChild) {
                    node.appendTo(mountedRoot)
                    root.push(node)
                } else {
                    error('mountedRoot is invalid, it should be a pixi element')
                }
            })
            
            return root.length > 1 ? root : root[0]
        } else {
            error('Parse template error, Please check the template string')
        }
    } else {
        error('the template should be string')
    }
}
