/**
 * Copyright Aquera Inc 2023
 *
 * This source code is licensed under the BSD-3-Clause license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {LitElement, html, CSSResultArray, TemplateResult, PropertyValues} from 'lit';
import { customElement, property, query, state} from 'lit/decorators.js';
import {styles} from './nile-table.css';
import NileElement from '../internal/nile-element';
import { NileTableBody } from '../nile-table-body';
import { NileTableCellItem } from '../nile-table-cell-item';
import { NileTableHeaderItem } from '../nile-table-header-item';


/**
 * Nile table component.
 *
 * @tag nile-table
 *
 */
@customElement('nile-table')
export class NileTable extends NileElement {
  @query('slot') defaultSlot: HTMLSlotElement;
	private rows:Array<NileTableBody>=[];
	private primaryRowWidths:Array<number>=[]
	private resizeObserver:ResizeObserver ;
	private debounceTimeout:any


	/**
	 * The styles for nile-table
	 * @remarks If you are extending this class you can extend the base styles with super. Eg `return [super(), myCustomStyles]`
	 */
	public static get styles(): CSSResultArray {
		return [styles];
	}
	connectedCallback(): void {
		super.connectedCallback()
		this.addEventListener('nile-body-load',this.handleRows)
	}

	protected firstUpdated(_changedProperties: PropertyValues): void {
		this.updateComplete.then(()=>{
			this.handleResizeObserver();
		})
	}


	/* #endregion */

	/* #region Methods */

	/**
	 * Render method
	 * @slot This is a slot test
	 */
	public render(): TemplateResult {
		return html`
			<slot @slotchange="${this.repaintTable}"></slot>
			`;
	}

	repaintTable(){
		this.realignStructure();
		this.handleBodyCssUpdate();
	}

	handleRows(e:CustomEvent){
		this.rows=[...this.rows,e.detail.comp]
	}

	handleBodyCssUpdate(){
    if (this.rows.length<2) return;
    const tableBodies = this.rows;
		const firstEl=tableBodies[0].shadowRoot?.querySelector<HTMLDivElement>('div.base');
		if(firstEl) {
			firstEl.style.borderTopRightRadius="var(--nile-radius-radius-xl)";
			firstEl.style.borderTopLeftRadius = 'var(--nile-radius-radius-xl)';
			firstEl.style.borderBottomRightRadius="0px";
			firstEl.style.borderBottomLeftRadius = '0px';
			firstEl.style.borderBottom = 'none';
		}
		tableBodies.forEach((tb,i)=>{
			if(i>0 && i<tableBodies.length-1){
				const el=tb.shadowRoot?.querySelector<HTMLDivElement>('div.base');
				if(el) {
					el.style.borderTopRightRadius="0px";
					el.style.borderTopLeftRadius = "0px";
					el.style.borderBottomRightRadius="0px";
					el.style.borderBottomLeftRadius = "0px";
					el.style.borderBottom = 'none';
				}
			}
		})
		const lastEl=tableBodies[tableBodies.length - 1].shadowRoot?.querySelector<HTMLDivElement>('div.base')
		if(lastEl){
			lastEl.style.borderTopRightRadius="0px";
			lastEl.style.borderTopLeftRadius = '0px';
			lastEl.style.borderBottomRightRadius="var(--nile-radius-radius-xl)";
			lastEl.style.borderBottomLeftRadius = 'var(--nile-radius-radius-xl)';
		}
	}

	getPrimaryColumnWidths(){
		const primaryTb=this.rows.find(tb=>tb.type=='primary')!;
		const widthArray=this.getTableCellFetchQuery(primaryTb).map((e:LitElement)=>e.clientWidth) as Array<number>
		return widthArray;
	}
	
	realignStructure(){
    if (this.rows.length<2) return;
		const primaryRowWidths=this.getPrimaryColumnWidths();
		const secondaryRows=this.rows.filter(tb=>tb.type!='primary');
		secondaryRows.forEach((row)=>{
			let elements=this.getTableCellFetchQuery(row)
			elements?.forEach((el:NileTableCellItem|NileTableHeaderItem,ind)=>{
				el.style.setProperty('--cell-width',primaryRowWidths.at(ind)+'px')
			})
		})
	}

	getTableCellFetchQuery(row:NileTableBody):Array<Element>{
		return row?.shadowRoot?.
			querySelector<HTMLSlotElement>('slot:not([name])')?.
			assignedElements()[0]
			.shadowRoot?.querySelector<HTMLSlotElement>('slot')?.
			assignedElements()!
	}

	handleResizeObserver(){
		const onResize = (entries:ResizeObserverEntry[]): void=> {
			for (let entry of entries) {
				if(this.debounceTimeout){
					clearTimeout(this.debounceTimeout);
				}
				this.debounceTimeout=setTimeout(() => {
					this.realignStructure();
					this.debounceTimeout=null;
				}, 50);
			}
		};
		this.resizeObserver=new ResizeObserver(onResize)
		this.resizeObserver.observe(this);
	}

	disconnectedCallback(): void {
		this.resizeObserver.disconnect()
		super.disconnectedCallback()
	}
	/* #endregion */
}

export default NileTable;

declare global {
  interface HTMLElementTagNameMap {
    'nile-table': NileTable;
  }
}