/**
 * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

import { BaseComponent } from '../components/base-component';
import { onHeaderResize } from './header';
import { isHiddenElement } from '../helpers/is-hidden-element';

export class Sidebar extends BaseComponent {
	/**
	 * Creates a sidebar component.
	 *
	 * @param element - The sidebar element.
	 */
	constructor( element ) {
		super( {
			isHidden: element.classList.contains( 'c-sidebar--collapsed' ),
			headerHeight: null
		} );

		this.elements = {
			sidebar: element,
			sidebarNav: element.querySelector( '.c-sidebar__nav' ),
			toggleVisibilityBtn: element.querySelector( '.js-sidebar-toggle-btn' )
		};
	}

	/**
	 * Initializes sidebar component on the page.
	 */
	static attach() {
		const sidebar = document.querySelector( '.js-sidebar' );

		if ( sidebar ) {
			new Sidebar( sidebar ).init();
		}
	}

	/**
	 * Initializes the sidebar component with event listeners.
	 */
	init() {
		const { toggleVisibilityBtn } = this.elements;

		toggleVisibilityBtn?.addEventListener( 'click', () => {
			this.setState( { isHidden: !this.state.isHidden } );
		} );

		// Listen for header resize events
		this.headerResizeUnsubscribe = onHeaderResize( height => {
			this.setState( { headerHeight: height } );
		} );

		this.render();
	}

	/**
	 * Renders the sidebar based on current state.
	 *
	 * @param prevState - Previous component state.
	 * @param state - Current component state.
	 */
	render( prevState, state = this.state ) {
		const { sidebar, sidebarNav } = this.elements;
		const { isHidden, headerHeight } = state;

		sidebar.classList.toggle( 'c-sidebar--collapsed', isHidden );

		if ( headerHeight !== null && !isHiddenElement( sidebar ) ) {
			sidebar.style.setProperty( '--header-height', `${ headerHeight }px` );
		}

		this.retrieveScrollbarPosition();
		this.storeScrollbarPositionEvent();

		document.addEventListener(
			'sidebar-folderstate:done',
			() => sidebarNav.classList.remove( 'c-sidebar__nav--loading' ),
			{ once: true }
		);
	}

	storeScrollbarPositionEvent() {
		const { sidebarNav } = this.elements;

		// Store the scroll position in sessionStorage before the page is unloaded.
		window.addEventListener( 'beforeunload', () => {
			sessionStorage.setItem( 'ckSidebarScroll', sidebarNav.scrollTop );
		} );
	}

	retrieveScrollbarPosition() {
		const { sidebar, sidebarNav } = this.elements;

		// Retrieve the stored scroll position from sessionStorage.
		const storedScrollPosition = sessionStorage.getItem( 'ckSidebarScroll' );

		// If a stored scroll position exists, scroll the sidebar to that position.
		if ( storedScrollPosition !== null ) {
			sidebarNav.scrollTop = Number( storedScrollPosition );
		}

		const activeElement = sidebar.querySelector( 'a.c-nav-tree__link--active' );

		activeElement?.scrollIntoView( {
			behavior: 'instant',
			block: 'nearest',
			inline: 'nearest'
		} );
	}
}

// c-sidebar__nav--loading
