/**
 * Fraction of measured width used for --main-circle-size when Auto Circle Size is on.
 * Slightly smaller than 1 so ring items clear clipping on small viewports.
 */
const DSM_CIRCLE_INFO_AUTO_SIZE_WIDTH_FACTOR = 0.8;

/**
 * When Auto Circle Size is on, keep --main-circle-size in sync with the container width.
 *
 * @param {HTMLElement} container .dsm-circle-info-container
 */
function dsmBindCircleInfoAutoSize( container ) {
	if ( ! container || container.getAttribute( 'data-circle-size-auto' ) !== 'on' ) {
		return;
	}
	const sizingEl = container.parentElement || container;
	const apply = () => {
		const raw = sizingEl.clientWidth;
		if ( raw <= 0 ) {
			return;
		}
		const inset = Math.round(
			raw * DSM_CIRCLE_INFO_AUTO_SIZE_WIDTH_FACTOR
		);
		if ( inset > 0 ) {
			container.style.setProperty( '--main-circle-size', inset + 'px' );
		}
	};
	apply();
	let ro;
	if ( 'undefined' !== typeof ResizeObserver ) {
		ro = new ResizeObserver( apply );
		ro.observe( sizingEl );
	}
}

class DSMCircleInfo {
	constructor( container ) {
		this.container = container;
		this.delay = this.container.dataset.delay;
		this.animation = this.container.dataset.animation;
		this.titleItemWrapper = this.container.querySelectorAll(
			'.dsm-circle-info-item-inner-wrapper'
		);
		this.titleWrapper = this.container.querySelectorAll(
			'.dsm-circle-info-button-wrapper'
		);
		this.contentWrapper = this.container.querySelectorAll(
			'.dsm-circle-info-content-wrapper'
		);
		this.contentWrapperInner = this.container.querySelectorAll(
			'.dsm-circle-info-content-inner-wrapper'
		);
		this.tabList = this.container.querySelector( '[role="tablist"]' );
		this.tabs = this.container.querySelectorAll( '[role="tab"]' );
		this.panels = this.container.querySelectorAll( '[role="tabpanel"]' );

		this.reducedMotion =
			'undefined' !== typeof window &&
			window.matchMedia &&
			window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches;

		const activeItemIndex = Array.from( this.titleItemWrapper ).findIndex(
			( item ) => {
				return item.classList.contains( 'dsm-circle-info-item-active' );
			}
		);

		this.currentActiveItem =
			activeItemIndex === -1 ? 0 : activeItemIndex;

		this.triggerType = this.container.dataset.trigger;

		this.config = {
			isAutoplay:
				this.container.dataset.autoplay === 'on' && ! this.reducedMotion,
			updateAngle: Number( this.container.dataset.updateangle ),
		};

		this.activate( this.currentActiveItem );

		this.init();
	}

	activate( index, options ) {
		const focusTab = options && options.focusTab;
		const n = this.titleItemWrapper.length;
		if ( n === 0 || index < 0 || index >= n ) {
			return;
		}

		this.titleItemWrapper.forEach( ( item, i ) => {
			const isSel = i === index;
			if ( isSel ) {
				item.classList.add( 'dsm-circle-info-item-active' );
				this.contentWrapper[ i ].classList.add(
					'dsm-circle-info-item-active'
				);
				this.contentWrapperInner[ i ].classList.add(
					'animated',
					this.animation
				);
			} else {
				item.classList.remove( 'dsm-circle-info-item-active' );
				this.contentWrapper[ i ].classList.remove(
					'dsm-circle-info-item-active'
				);
				this.contentWrapperInner[ i ].classList.remove(
					'animated',
					this.animation
				);
			}

			const tab = this.tabs[ i ];
			if ( tab ) {
				tab.setAttribute(
					'aria-selected',
					isSel ? 'true' : 'false'
				);
				tab.tabIndex = isSel ? 0 : -1;
			}
			if ( this.panels[ i ] ) {
				if ( isSel ) {
					this.panels[ i ].removeAttribute( 'hidden' );
				} else {
					this.panels[ i ].setAttribute( 'hidden', '' );
				}
			}
		} );

		this.currentActiveItem = index;

		if ( focusTab && this.tabs[ index ] ) {
			this.tabs[ index ].focus();
		}
	}

	init() {
		this.setActiveItem();
		this.bindTabListKeyboard();
		if ( this.config.isAutoplay ) {
			this.handleAutoplay();
		}
	}

	bindTabListKeyboard() {
		if ( ! this.tabList ) {
			return;
		}
		this.tabList.addEventListener( 'keydown', ( e ) => {
			const tabs = Array.from( this.tabs );
			if ( 0 === tabs.length ) {
				return;
			}
			const cur = tabs.indexOf(
				/** @type {Element} */ ( document.activeElement )
			);
			if ( cur === -1 ) {
				return;
			}
			let next = cur;
			if ( 'ArrowRight' === e.key || 'ArrowDown' === e.key ) {
				e.preventDefault();
				next = ( cur + 1 ) % tabs.length;
			} else if ( 'ArrowLeft' === e.key || 'ArrowUp' === e.key ) {
				e.preventDefault();
				next = ( cur - 1 + tabs.length ) % tabs.length;
			} else if ( 'Home' === e.key ) {
				e.preventDefault();
				next = 0;
			} else if ( 'End' === e.key ) {
				e.preventDefault();
				next = tabs.length - 1;
			} else {
				return;
			}
			this.activate( next, { focusTab: true } );
		} );
	}

	handleAutoplay() {
		setInterval( () => {
			const next =
				this.currentActiveItem >= this.titleWrapper.length - 1
					? 0
					: this.currentActiveItem + 1;
			this.activate( next );

			const computedStyle = getComputedStyle( this.container );
			const currentAngle =
				parseFloat( computedStyle.getPropertyValue( '--dsm-angle' ) ) ||
				0;
			const newAngle = currentAngle + this.config.updateAngle;

			if ( ! isNaN( newAngle ) ) {
				this.container.style.setProperty(
					'--dsm-angle',
					newAngle.toString()
				);
			}
		}, Number( this.delay ) );
	}

	setActiveItem() {
		this.titleWrapper.forEach( ( item, index ) => {
			if ( 'click' === this.triggerType ) {
				item.addEventListener( 'click', () => {
					this.activate( index );
				} );
			} else if ( 'hover' === this.triggerType ) {
				item.addEventListener( 'mouseenter', () => {
					this.activate( index );
				} );
			}
		} );
	}
}

window.addEventListener( 'load', () => {
	const circleInfoContainers = document.querySelectorAll(
		'.dsm-circle-info-container'
	);

	circleInfoContainers.forEach( ( container ) => {
		dsmBindCircleInfoAutoSize( container );
	} );

	circleInfoContainers.forEach( ( container ) => {
		container.classList.add( 'dsm_animate' );

		const waypoint = new Waypoint( {
			element: container,
			handler: function () {
				new DSMCircleInfo( container );
				this.destroy();
			},
			offset: '50%',
		} );
	} );
} );
