/**
 * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
 */

import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
import { Enter } from '@ckeditor/ckeditor5-enter';
import { Typing } from '@ckeditor/ckeditor5-typing';
import { Heading } from '@ckeditor/ckeditor5-heading';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
import { Undo } from '@ckeditor/ckeditor5-undo';
import { Clipboard } from '@ckeditor/ckeditor5-clipboard';
import { Indent } from '@ckeditor/ckeditor5-indent';
import { Widget, toWidget } from '@ckeditor/ckeditor5-widget';
import { Table, TableToolbar } from '@ckeditor/ckeditor5-table';
import {
	_parseModel,
	_setModelData,
	_getModelData
} from '@ckeditor/ckeditor5-engine';

import { modelList, stringifyList } from '../list/_utils/utils.js';
import { List } from '../../src/list.js';

ClassicEditor
	.create( document.querySelector( '#editor' ), {
		plugins: [ Enter, Typing, Heading, Paragraph, Undo, Clipboard, List, Indent, Widget, Table, TableToolbar ],
		toolbar: [ 'heading', '|', 'bulletedList', 'numberedList', 'outdent', 'indent', '|', 'insertTable', '|', 'undo', 'redo' ],
		table: {
			contentToolbar: [
				'tableColumn', 'tableRow', 'mergeTableCells', 'toggleTableCaption'
			]
		}
	} )
	.then( editor => {
		window.editor = editor;

		editor.model.schema.register( 'blockWidget', {
			isObject: true,
			isBlock: true,
			allowIn: '$root',
			allowAttributesOf: '$container'
		} );

		editor.conversion.for( 'editingDowncast' ).elementToElement( {
			model: 'blockWidget',
			view: ( modelItem, { writer } ) => {
				return toWidget( writer.createContainerElement( 'blockwidget', { class: 'block-widget' } ), writer );
			}
		} );

		editor.conversion.for( 'dataDowncast' ).elementToElement( {
			model: 'blockWidget',
			view: ( modelItem, { writer } ) => writer.createContainerElement( 'blockwidget', { class: 'block-widget' } )
		} );

		editor.model.schema.register( 'inlineWidget', {
			isObject: true,
			isInline: true,
			allowWhere: '$text',
			allowAttributesOf: '$text'
		} );

		editor.conversion.for( 'editingDowncast' ).elementToElement( {
			model: 'inlineWidget',
			view: ( modelItem, { writer } ) => toWidget(
				writer.createContainerElement( 'inlinewidget', { class: 'inline-widget' } ), writer, { label: 'inline widget' }
			)
		} );

		editor.conversion.for( 'dataDowncast' ).elementToElement( {
			model: 'inlineWidget',
			view: ( modelItem, { writer } ) => writer.createContainerElement( 'inlinewidget', { class: 'inline-widget' } )
		} );

		const model = '<paragraph listIndent="0" listItemId="000" listType="bulleted">A</paragraph>\n' +
			'<paragraph listIndent="0" listItemId="000" listType="bulleted">B</paragraph>\n' +
			'<paragraph listIndent="1" listItemId="002" listType="numbered">C</paragraph>\n' +
			'<paragraph listIndent="2" listItemId="003" listType="numbered">D</paragraph>\n' +
			'<paragraph listIndent="0" listItemId="004" listType="bulleted">E</paragraph>\n' +
			'<paragraph listIndent="0" listItemId="005" listType="bulleted">F</paragraph>';

		document.getElementById( 'data-input' ).value = model;
		document.getElementById( 'btn-process-input' ).click();
	} )
	.catch( err => {
		console.error( err.stack );
	} );

const copyOutput = async () => {
	if ( !window.navigator.clipboard ) {
		console.warn( 'Cannot copy output. Clipboard API requires HTTPS or localhost.' );
		return;
	}

	const output = document.getElementById( 'data-output' ).innerText;

	await window.navigator.clipboard.writeText( output );

	const copyButton = document.getElementById( 'btn-copy-output' );
	const label = document.createElement( 'span' );

	label.id = 'btn-copy-label';
	label.innerText = 'Copied!';

	copyButton.appendChild( label );

	window.setTimeout( () => {
		label.className = 'hide';
	},
	0 );

	window.setTimeout( () => {
		label.remove();
	}, 1000 );
};

const getListModelWithNewLines = stringifiedModel => {
	return stringifiedModel.replace( /<\/(paragraph|heading\d)>/g, '</$1>\n' );
};

const setModelDataFromAscii = () => {
	const asciiList = document.getElementById( 'data-input' ).value;
	const modelDataArray = asciiList.replace( /^[^']*'|'[^']*$/gm, '' ).split( '\n' );

	const editorModelString = modelList( modelDataArray );

	_setModelData( window.editor.model, editorModelString );
	document.getElementById( 'data-output' ).innerText = getListModelWithNewLines( editorModelString );
};

const createAsciiListCodeSnippet = stringifiedAsciiList => {
	const asciiList = stringifiedAsciiList.split( '\n' );

	const asciiListToInsertInArray = asciiList.map( ( element, index ) => {
		if ( index === asciiList.length - 1 ) {
			return `'${ element }'`;
		}

		return `'${ element }',`;
	} );

	const asciiListCodeSnippet = 'modelList( [\n\t' +
		asciiListToInsertInArray.join( '\n\t' ) +
		'\n] );';

	return asciiListCodeSnippet;
};

const setAsciiListFromModel = () => {
	const editorModelString = document.getElementById( 'data-input' ).value;
	const cleanedEditorModelString = editorModelString.replace( /^[^']*'|'[^']*$|\n|\r/gm, '' );

	const editorModel = _parseModel( cleanedEditorModelString, window.editor.model.schema );
	const asciiListCodeSnippet = createAsciiListCodeSnippet( stringifyList( editorModel ) );

	document.getElementById( 'data-output' ).innerText = asciiListCodeSnippet;
	_setModelData( window.editor.model, cleanedEditorModelString );
};

const processInput = () => {
	const dataType = document.querySelector( 'input[name="input-type"]:checked' ).value;

	if ( dataType === 'model' ) {
		setAsciiListFromModel();
	}

	if ( dataType === 'ascii' ) {
		setModelDataFromAscii();
	}

	window.editor.focus();

	if ( document.getElementById( 'chbx-should-copy' ).checked ) {
		copyOutput();
	}
};

const processEditorModel = () => {
	const dataType = document.querySelector( 'input[name="input-type"]:checked' ).value;

	if ( dataType === 'model' ) {
		const editorModelStringWithNewLines = getListModelWithNewLines( _getModelData( window.editor.model, { withoutSelection: true } ) );

		document.getElementById( 'data-input' ).value = editorModelStringWithNewLines;
	}

	if ( dataType === 'ascii' ) {
		const stringifiedEditorModel = _getModelData( window.editor.model, { withoutSelection: true } );
		const editorModel = _parseModel( stringifiedEditorModel, window.editor.model.schema );

		document.getElementById( 'data-input' ).value = createAsciiListCodeSnippet( stringifyList( editorModel ) );
	}

	processInput();
};

const onPaste = () => {
	if ( document.getElementById( 'chbx-process-on-paste' ).checked ) {
		window.setTimeout( processInput, 0 );
	}
};

const onHighlightChange = () => {
	document.querySelector( '.ck-editor' ).classList.toggle( 'highlight-lists' );
};

document.getElementById( 'btn-process-input' ).addEventListener( 'click', processInput );
document.getElementById( 'btn-process-editor-model' ).addEventListener( 'click', processEditorModel );
document.getElementById( 'btn-copy-output' ).addEventListener( 'click', copyOutput );
document.getElementById( 'data-input' ).addEventListener( 'paste', onPaste );
document.getElementById( 'chbx-highlight-lists' ).addEventListener( 'change', onHighlightChange );
