import type { TabPage } from './tab-page';
import { Prop, toNative } from 'vue-facing-decorator';
import PowerduckState from '../../app/powerduck-state';
import TsxComponent, { Component } from '../../app/vuetsx';
import { slotUnwrapper } from '../../common/slot-unwrapper';
import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
import { PortalUtils } from '../../common/utils/utils';
import Card from '../card/card';
import CardBody from '../card/card-body';
import CardHeader from '../card/card-header';
import HtmlLiteral from '../html-literal/html-literal';
import './css/tabs.css';

export enum TabsRenderMode {
	Normal = 0,
	SidePills = 1,
	SidePillsExtended = 2,
}

interface TabsArgs {
	renderMode?: TabsRenderMode;
	stickyOnMobile?: boolean;
	initialTabIndex?: number;
	allowTabSwitch?: boolean;
    wrapInCard?: boolean;
	cardHasShadow?: boolean;
	cardRenderMode?: 'default' | 'inlined';
	renderHiddenTabs?: boolean;
	onTabChange?: (index: number) => void;
}

@Component
class TabsComponent extends TsxComponent<TabsArgs> implements TabsArgs {
	@Prop() renderMode!: TabsRenderMode;
	@Prop() stickyOnMobile!: boolean;
	@Prop() initialTabIndex!: number;
	@Prop() allowTabSwitch!: boolean;
	@Prop() wrapInCard!: boolean;
	@Prop() cardHasShadow!: boolean;
	@Prop() renderHiddenTabs!: boolean;
	@Prop() cardRenderMode?: 'default' | 'inlined';
	@Prop() onTabChange?: (index: number) => void;
	registeredCount: number = null;
	activePageIndex: number = null;
	uuid: string = null;

	created() {
		if (this.initialTabIndex != null) {
			this.setActivePageIndex(this.initialTabIndex, true);
		} else {
			this.setActivePageIndex(0, true);
		}
	}

	mounted() {
		this.ensureStickyTabs();
	}

	updated() {
		this.ensureStickyTabs();
	}

	beforeUnmount() {
		if (this.uuid != null) {
			PowerduckState.unregisterStickyTabs(this.uuid);
		}
	}

	ensureStickyTabs(): void {
		if (this.uuid == null) {
			this.uuid = `t-${PortalUtils.randomString(8)}`;
		}

		if (this.stickyOnMobile == true) {
			PowerduckState.registerStickyTabs(this.uuid, {
				HasSticky: this.stickyOnMobile == true,
				AllowTabChange: this.allowTabSwitch != false,
			});
		}
	}

	getChildTabs(): typeof TabPage.prototype[] {
		return this.getSlotProperties('TabPage');
	}

	getContentCssClass(): string {
		if (this.allowTabSwitch != false) {
			return 'col-md-9 col-lg-10 tab-content';
		} else {
			return 'col-md-12 tab-content';
		}
	}

	getCardHasShadow(): boolean {
		if (this.cardHasShadow != null) {
			return this.cardHasShadow;
		}

		if (this.renderMode == TabsRenderMode.SidePillsExtended) {
			return true;
		}

		return false;
	}

	getCardRenderMode(): 'default' | 'inlined' {
		if (!isNullOrEmpty(this.cardRenderMode)) {
			return this.cardRenderMode;
		}

		if (this.renderMode == TabsRenderMode.SidePillsExtended) {
			return 'inlined';
		}

		return 'default';
	}

	getActivePageIndex(): number {
		if (this.renderHiddenTabs != true) {
			if (this.activePageIndex > this.getChildTabs().length - 1) {
				this.activePageIndex = 0;
			}

			return this.activePageIndex || 0;
		} else {
			return (this as any)._activeIndex || 0;
		}
	}

	setActivePageIndex(index: number, initial: boolean = false): void {
		if (this.renderHiddenTabs != true) {
			this.activePageIndex = index;
		} else {
			(this as any)._activeIndex = index;
		}

		if (!initial) {
			this.onTabChange?.(index);
		}
	}

	render(h) {
		if (this.renderMode == null || this.renderMode == TabsRenderMode.SidePills || this.renderMode == TabsRenderMode.SidePillsExtended) {
			return this.renderSidePillsMode(h);
		} else if (this.renderMode == TabsRenderMode.Normal) {
			return this.renderNormalMode(h);
		} else {
			console.error('Render mode not implemented');
			return <div>Render mode not implemented</div>;
		}
	}

	getTabHref(tab: typeof TabPage.prototype, index: number): string {
		if (this.renderHiddenTabs != true) {
			return 'javascript:';
		} else {
			return `#${this.uuid}-tab-${index}`;
		}
	}

	getActiveSlots(): any[] {
		const slots = slotUnwrapper(this.$slots.default?.(), 'TabPage');
		if (this.renderHiddenTabs != true) {
			return [slots[this.getActivePageIndex()]]; // return [this.$slots.default?.()[this.getActivePageIndex()]];
		} else {
			return slots; // return this.$slots.default?.();
		}
	}

	renderSidePillsMode(h) {
		const childTabs = this.getChildTabs();
		let activeIndex = this.getActivePageIndex();
		if (activeIndex > childTabs.length - 1) {
			activeIndex = 0;
		}

		const activeTab: typeof TabPage.prototype = childTabs[activeIndex] || ({} as any);
		const fadeOutMode = this.renderHiddenTabs == true;

		return (
			<div class={`row tabs-root side-pills-mode-${this.renderMode == TabsRenderMode.SidePillsExtended ? 'extended' : 'normal'}`}>
				{this.allowTabSwitch != false && (
					<div class={`col-md-3 col-lg-2 tab-buttons-wrap${this.stickyOnMobile ? ' main-nav-tabs-wrap' : ''}`}>
						<ul
							class={`nav nav-pills nav-pills-secondary nav-pills-icons flex-column ` + `nav-${childTabs.length}-items${this.stickyOnMobile ? ' main-nav-tabs' : ''}`}
							role="tablist"
						>
							{childTabs.map((tab, i) => (
								<li class="nav-item" data-uuid={tab.uuid} data-index={i}>
									<a
										class={`nav-link inv-tab-button${activeIndex == i ? ' active' : ''}`}
										id={`${this.uuid}-button-${i}`}
										data-bs-toggle={fadeOutMode ? 'tab' : null}
										data-bs-target={fadeOutMode ? this.getTabHref(tab, i) : null}
										href="javascript:"
										role="tab"
										onClick={() => {
											this.setActivePageIndex(i);
										}}
									>
										<i class={tab.icon}></i>
										{tab.escapeCaption != false
											? (
													<span>
														<span class="nav-caption-long">{tab.navCaption}</span>
														<span class="nav-caption-short">{tab.navCaptionShort || tab.navCaption}</span>
													</span>
												)
											: (
													<span>
														<span class="nav-caption-long">
															<HtmlLiteral innerHTML={tab.navCaption} />
														</span>
														<span class="nav-caption-short">
															<HtmlLiteral innerHTML={tab.navCaptionShort || tab.navCaption} />
														</span>
													</span>
												)}
									</a>
								</li>
							))}
						</ul>
					</div>
				)}

				<div class={this.getContentCssClass()}>
					{this.getActiveSlots().map((slot, i) => {
						// In navPills/hidden mode every pane renders up-front and Bootstrap toggles visibility
						// via CSS (no Vue re-render), so each pane must carry its OWN caption (pane i ↔ childTabs[i]).
						// Using the single shared `activeTab` froze every header at the first tab's caption.
						// In single-pane mode the only rendered pane is the active tab.
						const paneTab: typeof TabPage.prototype = (this.renderHiddenTabs == true ? childTabs[i] : activeTab) || activeTab;

						return (
							<div class={`tab-pane inv-tab-wrap fade show${activeIndex == i ? ' active' : ''}`} id={`${this.uuid}-tab-${i}`} role="tabpanel" data-button-id={`${this.uuid}-button-${i}`}>
								{this.wrapInCard === false
									? slot
									: (
										<Card hasShadow={this.getCardHasShadow()} renderMode={this.getCardRenderMode()}>
											<CardHeader title={paneTab.tabCaption || paneTab.navCaption} />
											<CardBody>{slot}</CardBody>
										</Card>
									)}
							</div>
						);
					})}
				</div>
			</div>
		);
	}

	renderNormalMode(h) {
		const childTabs = this.getChildTabs();
		const activeIndex = this.getActivePageIndex();

		return (
			<div class="tabs-normal-mode">
				{this.allowTabSwitch != false && (
					<div class={this.stickyOnMobile ? ' main-nav-tabs-wrap' : ''}>
						<ul class={`nav nav-pills nav-pills-primary ` + `nav-${childTabs.length}-items${this.stickyOnMobile ? ' main-nav-tabs' : ''}`} role="tablist">
							{childTabs.map((tab, i) => (
								<li class="nav-item" data-uuid={tab.uuid} data-index={i}>
									<a
										class={`nav-link inv-tab-button${activeIndex == i ? ' active' : ''}`}
										href="javascript:"
										role="tab"
										onClick={() => {
											this.setActivePageIndex(i);
										}}
									>
										{tab.icon != null && <i class={tab.icon}></i>}

										{tab.escapeCaption != false
											? (
													<span>
														<span class="nav-caption-long">{tab.navCaption}</span>
														<span class="nav-caption-short">{tab.navCaptionShort || tab.navCaption}</span>
													</span>
												)
											: (
													<span>
														<span class="nav-caption-long">
															<HtmlLiteral innerHTML={tab.navCaption} />
														</span>
														<span class="nav-caption-short">
															<HtmlLiteral innerHTML={tab.navCaptionShort || tab.navCaption} />
														</span>
													</span>
												)}
									</a>
								</li>
							))}
						</ul>
					</div>
				)}

				<div class="tab-content">
					{this.renderHiddenTabs != true && this.renderActiveTab(h)}
					{this.renderHiddenTabs == true && this.$slots.default?.().map(tab => <div>{tab}</div>)}
				</div>
			</div>
		);
	}

	renderActiveTab(h) {
		return <div>{slotUnwrapper(this.$slots.default?.())?.[this.getActivePageIndex()]}</div>;
	}
}

const Tabs = toNative(TabsComponent);
export default Tabs;
