import {css, html, LitElement} from 'lit'
import {customElement, property} from 'lit/decorators.js'
import type {FieldDefinition, FormConfig} from '../types'
import {DataPlane} from '../DataPlane'
import {Ex} from '../../util'
import uuid = Ex.uuid
import {LayoutSpec} from '../layout/Layout'
import {FormStateManager} from './State'

@customElement('cobalt-form')
export class Form extends LitElement {
    static override styles = css``

    @property({ attribute: false })
    plane?: DataPlane

    @property({ attribute: false })
    config?: FormConfig

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

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

    private stateManager?: FormStateManager

    getContextIdentifier(): string {
        return this.config?.sourceName || uuid()
    }

    getStateContextIdentifier(): string {
        return `${this.getContextIdentifier()}-state`
    }

    override render() {
        if ( !this.config || !this.plane ) {
            return html`Loading...`
        }

        this.plane.ensureSource(this.getContextIdentifier())
        this.plane.ensureSource(this.getStateContextIdentifier())

        if ( !this.stateManager ) {
            this.stateManager = new FormStateManager(
                this.getFields(this.layoutChildren || []),
                this.getContextIdentifier(),
                this.getStateContextIdentifier(),
                this.plane,
            )
        }

        const context = {
            ...this.parentContext,
            sourceName: this.getContextIdentifier(),
        }

        return html`
            <cobalt-layout
                .plane=${this.plane}
                .parentContext=${context}
                .layoutChildren=${this.layoutChildren}
            ></cobalt-layout>
        `
    }

    private getFields(layout: LayoutSpec[], fields: FieldDefinition[] = []): FieldDefinition[] {
        for ( const item of layout ) {
            if ( item.component === 'field' ) {
                if ( item.config ) {
                    fields.push(item.config as FieldDefinition)
                }

                continue
            }

            if ( item.component === 'form' || !item.layoutChildren ) {
                continue
            }

            this.getFields(item.layoutChildren, fields)
        }

        return fields
    }
}
