declare namespace Component {
    type spriteImage = string | number | PIXI.Texture | HTMLCanvasElement | HTMLVideoElement | HTMLImageElement
    type addon = (core: any) => void
    type type = "Text" | "Sprite" | "View" | "Rect" | "Circle" | "AnimatedSprite" 
    interface config {
        uiDesignWidth?: number
        debug?: boolean
    }
}

declare namespace Temp {
    type styleKey = keyof Layout.style
    interface styleObj {
        [selector: string]: string | any
    }
    interface extra {
        [key: string]: any
    }
    type style = (styleObj: styleObj) => void
    type render = (template: string, mountedRoot: any, extra?: extra) => Layout.element
}

declare namespace Layout {
    type element = componentAnimateSprite | componentSprite | componentText | componentRect | componentCircle
    interface style {
        width?: string | number,
        height?: string | number,

        left?: string | number,
        right?: string | number,
        bottom?: string | number,
        top?: string | number,
        centerX?: string | number,
        centerY?: string | number,
        center?: string | number | { x: number, y: number } | any[] 

        rotation?: number | string,
        opacity?: number | string,
        backgroundColor?: number | string
        backgroundImage?: PIXI.Texture
        backgroundFrame?: number[] | string
        borderWidth?: number,
        borderColor?: number | string,
        anchor?: { x: number, y: number } | number | string,
        scale?: { x: number, y: number } | number | string,
        zIndex?: number | string,
        // 文字水平排列
        textAlign?: 'left' | 'center' | 'right' | number
        // 文字垂直排队
        textJustify?: 'top' | 'center' | 'bottom' | number
        content?: string | number,
        color?: string | number,
        fontSize?: number | string,
        fontWeight?: "normal" | "bold" | "bolder" | "lighter" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900"
        fontStyle?: "normal" | "italic" | "oblique"
        fontFamily?: string | string[]
        lineHeight?: number,
        [restProps: string]: any,

        // AnimatedSprite 专属
        animatedFrames?: PIXI.Texture[] | string | string[]
        animatedLoop?: boolean | string
        animatedSpeed?: number | string
    }
    interface point {
        x: number,
        y: number,
    }
    interface size {
        width: number,
        height: number,
    }
    interface scale {
        x: number,
        y: number,
    }
    interface config {
        uiDesignRatio: number
        Component: {
            on: (name: string, closure: () => void) => void
            emit: (name: string, data?: any) => void
        }
    }
    interface transform {
        rotation: (angle: number | string) => number
        length: (containerLength: number, value: string | number) => number,
        pos: (containerLength: number, spriteLength: number, value: number | string) => number,
        actualScale: (container: element) => { x: number, y: number },
        actualSize: (target: element) => size,
        getRatio: (target: element) => number
        elementSize: (
            target: element,
            style: style,
            containerSize: size,
        ) => size
        elementPos: (
            size: size,
            style: style,
            containerSize: size,
        ) => {
            x: number,
            y: number,
            rotation: number,
        }
        container: (element: element) => containerStatus
        rlayout2pixilayout: (container: containerStatus, anchor: point, rlayout: layout) => layout
        pixilayout2rlayout: (container: containerStatus, anchor: point, pixilayout: layout) => layout
    }
    interface containerStatus {
        element: element,
        width: number,
        height: number,
        ratio: number,
        scale: {
            x: number,
            y: number,
        },
        refresh?: boolean
    }
    interface layout {
        width: number
        height: number
        x: number
        y: number
        rotation: number
    }
    interface updateOption {
        refreshStyle?: boolean,
        updateChild?: boolean,
        replaceStyle?: boolean,
    }
}

interface componentBase {
    layout: {
        update: (style?: Layout.style) => void
        setScale: (scale: number) => void
    }
    appendTo: (container: any) => void
    append: (child: any) => void
    before: (element: any) => void
    after: (element: any) => void
    insertBefore: (element: any) => void
    insertAfter: (element: any) => void
    remove: () => void
    getRelativeBounds: () => { width: number, height: number, x: number, y: number }
    getGlobalBounds: () => { width: number, height: number, x: number, y: number }
    setStyle: (style: Layout.style, options?: {
        refreshStyle?: boolean,
        updateChild?: boolean,
    }) => void
    getStyle: (key?: string, options?: {
        refreshStyle?: boolean,
    }) => any
    transformStyle: (style: Layout.style) => Layout.layout
    type: string
}

interface componentAnimateSprite extends PIXI.Sprite, componentBase {
    replay(): void
}
interface componentSprite extends PIXI.Sprite, componentBase {}
interface componentText extends PIXI.Text, componentBase {}
interface componentRect extends PIXI.Text, componentBase {}
interface componentCircle extends PIXI.Text, componentBase {}

declare module '@amoy/components' {
    function configComponents(config?: Component.config): void
    function Sprite(image: Component.spriteImage, style?: Layout.style): componentSprite
    function AnimatedSprite(animatedFrames: PIXI.Texture[] | string | string[], style?: Layout.style): componentSprite
    function Text(centent: string, style?: Layout.style): componentText
    function Rect(style?: Layout.style): componentRect
    function Circle(style?: Layout.style): componentCircle
    function View(style?: Layout.style): componentSprite
    const render: Temp.render
    const style: Temp.style
    const Utils: {
        forin: (object: object, fn: (key?: string, value?: any) => void) => void,
        type: (target: any) => 'boolean' | 'number' | 'string' | 'function' | 'array' | 'date' | 'regExp' | 'object' | 'error' | 'symbol'
        getValue: (root: any, get: string) => any
        setValue: (tar: any, key: string, value: any) => void
        extend: (...args) => object
        string2hex: (v: any) => any
    }
}