import {html, LitElement} from 'lit'
import {customElement, property} from 'lit/decorators.js'
import {DataPlane} from '../DataPlane'
import {FieldType} from '../types'

export type LayoutSpec = {
    component: string
    config?: unknown
    layoutChildren?: LayoutSpec[]
}

export type LayoutContext = {
    plane: DataPlane
    config: any
    parentContext: Record<string, any>
    layoutChildren?: LayoutSpec[]
}

export type LayoutComponent = {
    name: string
    factory: (context: LayoutContext) => unknown,  // fixme
}

@customElement('cobalt-layout')
export class Layout extends LitElement {
    @property({ attribute: false })
    plane?: DataPlane

    @property({ attribute: false })
    parentContext: Record<string, any> = {}

    @property({ attribute: false })
    layoutChildren?: LayoutSpec[]

    private registry: Record<string, LayoutComponent> = {
        row: {
            name: 'row',
            factory: context => html`
                <cobalt-row
                        .plane=${context.plane}
                        .layoutChildren=${context.layoutChildren}
                        .parentContext=${context.parentContext}
                ></cobalt-row>
            `
        },
        col: {
            name: 'col',
            factory: context => html`
                <cobalt-col
                    .plane=${context.plane}
                    .layoutChildren=${context.layoutChildren}
                    .parentContext=${context.parentContext}
                ></cobalt-col>
            `
        },
        group: {
            name: 'group',
            factory: context => html`
                <cobalt-group
                    .plane=${context.plane}
                    .config=${context.config}
                    .layoutChildren=${context.layoutChildren}
                    .parentContext=${context.parentContext}
                ></cobalt-group>
            `
        },
        card: {
            name: 'card',
            factory: context => html`
                <cobalt-card
                    .plane=${context.plane}
                    .config=${context.config}
                    .layoutChildren=${context.layoutChildren}
                    .parentContext=${context.parentContext}
                ></cobalt-card>
            `
        },
        form: {
            name: 'form',
            factory: context => html`
                <cobalt-form
                    .plane=${context.plane}
                    .config=${context.config}
                    .layoutChildren=${context.layoutChildren}
                    .parentContext=${context.parentContext}
                ></cobalt-form>
            `
        },
        field: {
            name: 'field',
            factory: context => html`
                <cobalt-form-field
                    .plane=${context.plane}
                    .config=${context.config}
                    .parentContext=${context.parentContext}
                ></cobalt-form-field>
            `
        },
        table: {
            name: 'table',
            factory: context => html`
                <cobalt-table
                    .plane=${context.plane}
                    .config=${context.config}
                    .parentContext=${context.parentContext}
                ></cobalt-table>
            `
        },
    }

    private spec: LayoutSpec = {
        component: 'card',
        config: {
            display: 'People',
        },
        layoutChildren: [
            {
                component: 'table',
                config: {
                    sourceName: 'test-list-1',
                    rowKey: 'rows',
                    fields: [
                        {
                            key: 'first_name',
                            display: 'First Name',
                            type: FieldType.text,
                        },
                        {
                            key: 'last_name',
                            display: 'Last Name',
                            type: FieldType.text,
                            sort: 'asc',
                        },
                    ],
                },
            },
        ],
    }

    override render() {
        if ( !this.layoutChildren ) {
            return this.makeComponent(this.spec)
            // return html`...`
        }

        return html`
            ${this.layoutChildren.map(child => this.makeComponent(child))}
        `
    }

    private makeComponent(spec: LayoutSpec) {
        const factory = this.registry[spec.component]
        if ( !factory ) {
            console.error('Cannot find component factory for spec:', spec)
            return html`...`
        }

        const context: LayoutContext = {
            plane: this.getDataPlane(),
            config: spec.config || {},
            parentContext: this.parentContext,
            layoutChildren: spec.layoutChildren,
        }

        return factory.factory(context)
    }

    private dp?: DataPlane
    private getDataPlane(): DataPlane {
        if ( this.plane ) {
            return this.plane
        }

        if ( this.dp ) {
            return this.dp
        }

        return this.dp = new DataPlane()
    }
}
