import { getModules } from '../../utils/module-utils';

export const SEARCH_KEY = 'search';

export { getModules };

/**
 * @function applyColumnMove
 * @description Move a column and update prevId chaining.
 *
 * @since 6.1.3
 *
 * @param {Array}  sourceData The source data array for the columns.
 * @param {number} fromIndex  The index of the column being moved.
 * @param {number} toIndex    The index to move the column to.
 *
 * @return {object|null} The updated move payload or null if move is invalid.
 */
export const applyColumnMove = ( sourceData, fromIndex, toIndex ) => {
	if (
		! Array.isArray( sourceData ) ||
		sourceData.length === 0 ||
		typeof fromIndex !== 'number' ||
		typeof toIndex !== 'number' ||
		fromIndex === toIndex ||
		fromIndex < 0 ||
		toIndex < 0 ||
		fromIndex >= sourceData.length ||
		toIndex >= sourceData.length
	) {
		return null;
	}

	const updatedData = sourceData.map( ( column ) => ( { ...column } ) );
	const movedColumn = updatedData[ fromIndex ];

	let oldNextColumn = null;
	let newNextColumn = null;

	// Fill the hole left by the moved column.
	if ( fromIndex === updatedData.length - 1 ) {
		// Is last column in kanban, nothing to update.
	} else {
		// has next column, update next column prevId to moved column prevId.
		oldNextColumn = updatedData[ fromIndex + 1 ];
		if ( oldNextColumn ) {
			oldNextColumn.prevId = movedColumn.prevId;
		}
	}

	// Move column.
	updatedData.splice( fromIndex, 1 );
	updatedData.splice( toIndex, 0, movedColumn );

	// Update moved column's previous ID and the new next column's previous ID.
	if ( toIndex !== 0 ) {
		// Moved column is not the first card, updated moved column prevId.
		const newPrevColumn = updatedData[ toIndex - 1 ];
		movedColumn.prevId = newPrevColumn.id;
	} else {
		movedColumn.prevId = null;
	}
	if ( toIndex !== updatedData.length - 1 ) {
		// Moved column is not last column, update new next column prevId.
		newNextColumn = updatedData[ toIndex + 1 ];
		newNextColumn.prevId = movedColumn.id;
	}

	return {
		updatedData,
		movedColumn,
		oldNextColumn,
		newNextColumn,
	};
};

/**
 * @function applyCardMove
 * @description Move a card and update prevId chaining.
 *
 * @since 6.1.3
 *
 * @param {Array}  sourceData The source data array for the columns.
 * @param {string} fromId     The id of the column the card is being moved from.
 * @param {string} toId       The id of the column the card is being moved to.
 * @param {number} fromIndex  The index of the card being moved.
 * @param {number} toIndex    The index to move the card to.
 * @param {string} kanbanId   The id of the Kanban board.
 *
 * @return {object|null} The updated move payload or null if move is invalid.
 */
export const applyCardMove = ( sourceData, fromId, toId, fromIndex, toIndex, kanbanId ) => {
	if (
		! Array.isArray( sourceData ) ||
		sourceData.length === 0 ||
		! fromId ||
		! toId ||
		typeof fromIndex !== 'number' ||
		typeof toIndex !== 'number'
	) {
		return null;
	}

	const updatedData = sourceData.map( ( column ) => ( { ...column } ) );
	let fromColumn = updatedData.find( ( column ) => `${ kanbanId }-${ column.id }` === fromId );
	let toColumn = updatedData.find( ( column ) => `${ kanbanId }-${ column.id }` === toId );

	if ( ! fromColumn || ! toColumn ) {
		return null;
	}

	fromColumn = {
		...fromColumn,
		cards: Array.from( fromColumn.cards || [] ),
	};
	toColumn = {
		...toColumn,
		cards: Array.from( toColumn.cards || [] ),
	};

	if ( fromColumn.id === toColumn.id ) {
		fromColumn = toColumn;
	}

	if (
		fromIndex < 0 ||
		toIndex < 0 ||
		fromIndex >= fromColumn.cards.length ||
		toIndex > toColumn.cards.length ||
		( fromColumn.id === toColumn.id && fromIndex === toIndex )
	) {
		return null;
	}

	const movedCard = fromColumn.cards[ fromIndex ];
	let oldNextCard = null;
	let newNextCard = null;

	// placeholder for moving card logic.
	const notFiltered = true; // @todo: get from filter module state.
	if ( notFiltered ) {
		// Fill the hole left by the moved card.
		if ( fromColumn.cards.length === 1 || fromIndex === fromColumn.cards.length - 1 ) {
			// is only card or last card in column, nothing to update.
		} else {
			// has next card, update next card prevId to moved card prevId.
			oldNextCard = fromColumn.cards[ fromIndex + 1 ];
			if ( oldNextCard ) {
				oldNextCard.prevId = movedCard.prevId;
			}
		}
	}

	// Move card.
	fromColumn.cards.splice( fromIndex, 1 );
	toColumn.cards.splice( toIndex, 0, movedCard );

	if ( notFiltered ) {
		// Update moved card's previous ID and the new next card's previous ID.
		if ( toIndex !== 0 ) {
			// Moved card is not first card, update moved card prevId.
			const newPrevCard = toColumn.cards[ toIndex - 1 ];
			movedCard.prevId = newPrevCard.id;
		} else {
			movedCard.prevId = null;
		}
		if ( toIndex !== toColumn.cards.length - 1 ) {
			// Moved card is not last card, update new next card prevId.
			newNextCard = toColumn.cards[ toIndex + 1 ];
			newNextCard.prevId = movedCard.id;
		}
	}

	const finalData = updatedData.map( ( column ) => {
		if ( fromColumn.id === toColumn.id && column.id === toColumn.id ) {
			return toColumn;
		}
		if ( column.id === fromColumn.id ) {
			return fromColumn;
		}
		if ( column.id === toColumn.id ) {
			return toColumn;
		}
		return column;
	} );

	return {
		updatedData: finalData,
		movedCard,
		oldNextCard,
		newNextCard,
		fromColumn,
		toColumn,
	};
};
