/**
 * 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, PropertyValueMap } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { styles } from './nile-stepper.css';
import NileElement from '../internal/nile-element';
import { watch } from '../internal/watch';
import { classMap } from 'lit/directives/class-map.js';
import { updateItemsInManualMode } from './stepper-utils';


/**
 * Nile stepper component.
 *
 * @tag nile-stepper
 *
 */
@customElement('nile-stepper')
export class NileStepper extends NileElement {

	@property({ type: Boolean, attribute: 'vertical' }) isVertical: boolean = false;
	@property({ type: Boolean, attribute: true, reflect:true }) contentBelow: boolean = false;
	@property({ type: Number, attribute: true, reflect:true }) currentStep: number = 0;
	@property({ type: Number, attribute: true, reflect:true  }) completedStep: number = 0;
	@property({ type: String, attribute: true, reflect:true  }) size: 'sm' | 'lg' = 'lg';
	@property({ type: String, attribute: true, reflect:true  }) icon: string = 'tick';
	@property({ type: Boolean, attribute: true, reflect:true }) manual: boolean = false;

	protected update(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void{
    super.update(changedProperties);
		if(changedProperties.has('currentStep') || changedProperties.has('completedStep') || changedProperties.has('manual')){
			this.updateItems();
		}
	}

	@watch('currentStep')
	handleCurrentStepChanges() {
		this.updateItems();
		this.emit('nile-current-change', { value: this.currentStep });
	}

	@watch('completedStep')
	handleCompletedStepChanges() {
		this.updateItems()
		this.emit('nile-completed-change', { value: this.completedStep });
	}
	
	private updateItems() {
		const items: any = [...this.querySelectorAll(this.isVertical ? 'nile-vertical-stepper-item' : 'nile-stepper-item')];
		if (!items.length) return;
		const haveFlex = items.length < 3;

		if (this.manual) {
			// Manual mode: use inline properties from each item
			updateItemsInManualMode(items, {
				icon: this.icon,
				size: this.size,
				contentBelow: this.contentBelow,
				manual: this.manual,
				isVertical: this.isVertical
			}, haveFlex);
		} else {
			// Automatic mode: use currentStep and completedStep properties
			const current = (this.currentStep == 0 || this.currentStep > items.length) ? 1 : this.currentStep;
			const calculatedCompleted = this.completedStep > items.length ? current : this.completedStep < current ? current : this.completedStep;
			const completed = this.completedStep > items.length ? 0 : this.completedStep;

			items.forEach((el: any, index: number) => {
				// set item is complete and is current values
				if (index + 1 < current) {
					el.isComplete = true;
					el.isCurrent = false;
				}
				else if (index + 1 == current) {
					if (index + 1 <= calculatedCompleted) el.isComplete = true;
					else el.isComplete = false;
					el.isCurrent = true;
				}
				else {
					if (index + 1 <= calculatedCompleted) el.isComplete = true;
					else el.isComplete = false;
					el.isCurrent = false;
				}

				// Reset and set isLast and isFirst
				el.isFirst = false;
				el.isLast = false;
				if (index == 0) el.isFirst = true;
				if (index == items.length - 1) el.isLast = true;

				// setting default values
				el.currentStepValue = current;
				el.calculatedCompletedStepValue = calculatedCompleted;
				el.completedStepValue = completed;

				el.icon = this.icon;
				el.size = this.size;
				el.value = index + 1;
				el.contentBelow = this.contentBelow;
				el.isManualMode = this.manual;
				if (index == 0 || index == items.length - 1) {
					el.haveFlex = haveFlex;
				}
			});
		}
	}

	/**
	 * The styles for nile-stepper
	 * @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];
	}

	/* #endregion */

	/* #region Methods */

	/**
	 * Render method
	 * @slot This is a slot test
	 */
	public render(): TemplateResult {
		return html`
			<div part="stepper" class=${classMap({
				'nile-stepper':true,
				'nile-stepper--horizontal':!this.isVertical,
				'nile-stepper--vertical':this.isVertical
			})}>
				<slot
					@slotchange=${this.updateItems}
				></slot>
			</div>
			`;
	}

	/* #endregion */
}

export default NileStepper;

declare global {
	interface HTMLElementTagNameMap {
		'nile-stepper': NileStepper;
	}
}
