import { findOptimalInsertionPosition, checkSelectionOnObject, isWidget, toWidget } from 'ckeditor5/src/widget';

export function toMediaWidget( viewElement, writer) {
	writer.setCustomProperty( 'media', true, viewElement );

	return toWidget( viewElement, writer, {} );
}

export function isMediaWidget( viewElement ) {
	return !!viewElement.getCustomProperty( 'media' ) && isWidget( viewElement );
}

export function getSelectedMediaWidget( selection ) {
	const viewElement = selection.getSelectedElement();

	if ( viewElement && isMediaWidget( viewElement ) ) {
		return viewElement;
	}

	return null;
}

export function isMedia( modelElement ) {
	return !!modelElement && modelElement.is( 'element', 'media' );
}

export function insertMedia( model, attributes = {}, insertPosition = null ) {
	model.change( writer => {
		const mediaElement = writer.createElement( 'media', attributes );

		const insertAtSelection = insertPosition || findOptimalInsertionPosition( model.document.selection, model );

		model.insertContent( mediaElement, insertAtSelection );

		if ( mediaElement.parent ) {
			writer.setSelection( mediaElement, 'on' );
		}
	} );
}

export function isMediaAllowed( model ) {
	const schema = model.schema;
	const selection = model.document.selection;

	return isMediaAllowedInParent( selection, schema, model ) &&
		!checkSelectionOnObject( selection, schema ) &&
		isInOtherMedia( selection );
}

export function getViewMediaFromWidget( figureView ) {
	const figureChildren = [];

	for ( const figureChild of figureView.getChildren() ) {
		figureChildren.push( figureChild );

		if ( figureChild.is( 'element' ) ) {
			figureChildren.push( ...figureChild.getChildren() );
		}
	}

	return figureChildren.find( viewChild => viewChild.is( 'element', 'media' ) );
}

function isMediaAllowedInParent( selection, schema, model ) {
	const parent = getInsertMediaParent( selection, model );

	return schema.checkChild( parent, 'media' );
}

function isInOtherMedia( selection ) {
	return [ ...selection.focus.getAncestors() ].every( ancestor => !ancestor.is( 'element', 'media' ) );
}

function getInsertMediaParent( selection, model ) {
	const insertAt = findOptimalInsertionPosition( selection, model );

	const parent = insertAt.parent;

	if ( parent.isEmpty && !parent.is( 'element', '$root' ) ) {
		return parent.parent;
	}

	return parent;
}
