import {css, html, LitElement} from 'lit'
import {customElement, property} from 'lit/decorators.js'
import {unsafeHTML} from 'lit/directives/unsafe-html.js'
import {DataPlane} from '../DataPlane'
import type {FieldDefinition, ListConfig} from '../types'
import {FieldType} from '../types'
import {IBehaviorSubject, Unsubscribe} from '../../BehaviorSubject'
import {Ex} from '../../util'
import dateToDisplay = Ex.dateToDisplay

@customElement('cobalt-table')
export class Table extends LitElement {
    static override styles = css`
        table {
            border-collapse: collapse;
            width: 100%;
        }

        td, th {
            border: 1px solid #ccc;
            text-align: left;
            padding: 7px;
        }
    `

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

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

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

    private data: Record<string, any>[] = []

    private dataSub?: Unsubscribe
    private rowField?: IBehaviorSubject<unknown>

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

        if ( !this.dataSub ) {
            this.plane.ensureSource(this.config.sourceName)

            this.rowField = this.plane
                .getField(this.config.sourceName, this.config.rowKey)

            if ( this.rowField ) {
                this.dataSub = this.rowField
                    ?.subscribe(rows => {
                        this.updateData(rows)
                        this.requestUpdate()
                    })

                this.updateData(this.rowField.value())
            }
        }

        return html`
            <table>
                <tr>
                    <th class="row-num">#</th>
                    ${this.config.fields.map(f => this.renderHeader(f))}
                </tr>
                ${this.data.map((r, i) => this.renderRow(i, r))}
            </table>
        `
    }

    private updateData(rows: unknown) {
        if ( !Array.isArray(rows) ) {
            console.error('Could not update table data: rows not an array', rows)
            return
        }

        this.data = rows
    }

    private renderHeader(field: FieldDefinition) {
        return html`
            <th>${field.display}</th>
        `
    }

    private renderRow(idx: number, row: Record<string, any>) {
        const cols = this.config!.fields
            .map(field => {
                if ( field.type === FieldType.html ) {
                    return html`
                        <td>${unsafeHTML(row[field.key] || '')}</td>
                    `
                }

                if ( field.type === FieldType.date ) {
                    return html`
                        <td>${row[field.key] ? dateToDisplay(new Date(row[field.key])) : ''}</td>
                    `
                }

                // fixme: handle select

                if ( field.type === FieldType.bool ) {
                    return html`
                        <td style="color: ${row[field.key] ? 'darkgreen' : 'darkred'}; font-weight: 500">
                            ${row[field.key] ? 'Yes' : 'No'}
                        </td>
                    `
                }

                return html`
                    <td>${row[field.key] || ''}</td>
                `
            })

        return html`<tr>
            <td>${idx+1}</td>
            ${cols}
        </tr>`
    }
}
