import React, { useState, useRef, useEffect } from 'react';
import { __ } from '@wordpress/i18n';
import Quill from 'quill';
import ImageResize from 'quill-image-resize-module-react';
import ImageUploader from 'quill-image-uploader';
import BlotFormatter from 'quill-blot-formatter';
import Table from 'quill-table';
import htmlEditButton from 'quill-html-edit-button';
import Button from '@QPComponents/Button';
import ReactModal from '@QPComponents/Modal/ReactModal';
import 'quill/dist/quill.snow.css';
import './styles.scss';

// custom HTML
const BlockEmbed = Quill.import( 'blots/block/embed' );
// video
class CustomVideoBlot extends BlockEmbed {
	static create( value ) {
		const node = super.create();
		node.setAttribute( 'src', value );
		node.setAttribute( 'controls', true );
		node.setAttribute( 'class', 'quizpress-custom-video' );
		node.setAttribute( 'data-blot-formatter-unclickable-bound', true ); // Remove this attribute
		return node;
	}

	static value( node ) {
		return node.getAttribute( 'src' );
	}
}

CustomVideoBlot.blotName = 'customVideo';
CustomVideoBlot.tagName = 'video';
Quill.register( CustomVideoBlot );

// audio
class CustomAudioBlot extends BlockEmbed {
	static create( value ) {
		const node = super.create();
		node.setAttribute( 'src', value );
		node.setAttribute( 'controls', true );
		node.setAttribute( 'class', 'quizpress-custom-audio' );
		node.setAttribute( 'data-blot-formatter-unclickable-bound', true ); // Remove this attribute
		return node;
	}

	static value( node ) {
		return node.getAttribute( 'src' );
	}
}

CustomAudioBlot.blotName = 'customAudio';
CustomAudioBlot.tagName = 'audio';
Quill.register( CustomAudioBlot );

class CustomHTMLBlot extends BlockEmbed {
	static create( value ) {
		const node = super.create();
		node.innerHTML = value;
		return node;
	}

	static value( node ) {
		return node.innerHTML;
	}
}

CustomHTMLBlot.blotName = 'customHTML';
CustomHTMLBlot.tagName = 'div'; // You can change the tag as needed

Quill.register( CustomHTMLBlot );

// image upload
const Image = Quill.import( 'formats/image' );
class CustomImage extends Image {
	static create( value ) {
		const node = super.create( value );
		if ( typeof value === 'object' ) {
			node.setAttribute( 'src', value.url );
			if ( value.width ) {
				node.setAttribute( 'width', value.width );
			}
			if ( value.height ) {
				node.setAttribute( 'height', value.height );
			}
			if ( value.style ) {
				node.setAttribute( 'style', value.style );
			}
		}
		return node;
	}

	static value( domNode ) {
		return {
			url: domNode.getAttribute( 'src' ),
			width: domNode.getAttribute( 'width' ),
			height: domNode.getAttribute( 'height' ),
			style: domNode.getAttribute( 'style' ),
		};
	}

	format( name, value ) {
		if ( name === 'width' || name === 'height' ) {
			if ( value ) {
				this.domNode.setAttribute( name, value );
			} else {
				this.domNode.removeAttribute( name );
			}
		} else {
			super.format( name, value );
		}
	}
}

// Register modules
Quill.register( 'modules/imageUploader', ImageUploader );
Quill.register( 'modules/imageResize', ImageResize );
Quill.register( 'modules/blotFormatter', BlotFormatter );
Quill.register( 'modules/htmlEditButton', htmlEditButton );
Quill.register( 'modules/table', Table );
Quill.register( CustomImage, true );

export default function BlockEditor( {
	name,
	defaultValue,
	saveValueHandler,
	suffix,
	isCustomHTML = false,
} ) {
	const quillRef = useRef( null );
	const [ customHTML, setCustomHTML ] = useState( '' );
	const [ showCustomInserter, isShowCustomInserter ] = useState( false );
	const isInitialized = useRef( false );
	const showCustomHTML = isCustomHTML ? [ [ 'customHTML' ] ] : [];

	useEffect( () => {
		if ( isInitialized.current ) {
			return;
		}

		const quill = new Quill( `#editor-container--${ suffix }`, {
			modules: {
				toolbar: {
					container: [
						[ { font: [] } ],
						[ { header: [ '1', '2', '3', '4', '5', '6' ] } ],
						[ { size: [] } ],
						[
							'bold',
							'italic',
							'underline',
							'strike',
							'blockquote',
							'code-block',
						],
						[ { color: [] }, { background: [] } ],
						[
							{ list: 'ordered' },
							{ list: 'bullet' },
							{ indent: '-1' },
							{ indent: '+1' },
							{ align: [] },
						],
						[ { script: 'sub' }, { script: 'super' } ],
						[ { direction: 'rtl' } ],
						[ 'image', 'link' ],
						[ 'table' ],
						[ 'clean' ],
						[ 'pdf' ],
						[ 'audio' ],
						[ 'video' ],
						...showCustomHTML,
					],
					handlers: {
						image: () => handleFileUpload( 'image' ),
						pdf: () => handleFileUpload( 'pdf' ),
						customHTML: () => isShowCustomInserter( true ),
						audio: () => handleFileUpload( 'mp3' ),
						video: () => handleFileUpload( 'video' ),
					},
				},
				clipboard: {
					matchVisual: false,
				},
				blotFormatter: {},
				htmlEditButton: {
					syntax: false,
				},
				'better-table': {
					operationMenu: {
						items: {
							unmergeCells: {
								text: 'Unmerge Cells',
							},
						},
					},
					table: true, // Enable table support
				},
			},
			theme: 'snow',
		} );

		quillRef.current = quill;
		isInitialized.current = true;

		if ( defaultValue ) {
			quill.clipboard.dangerouslyPasteHTML( defaultValue );
		}

		const handleChange = () => {
			const content = quill.root.innerHTML;
			saveValueHandler( name, content );
		};

		quill.on( 'text-change', handleChange );

		return () => {
			quill.off( 'text-change', handleChange );
		};
	}, [ name, saveValueHandler, suffix ] );

	useEffect( () => {
		if ( ! isInitialized.current || ! quillRef.current ) {
			return;
		}

		const quill = quillRef.current;
		if ( quill.root.innerHTML !== defaultValue ) {
			const selection = quill.getSelection();
			quill.clipboard.dangerouslyPasteHTML( defaultValue );

			if ( selection ) {
				setTimeout( () =>
					quill.setSelection( selection.index, selection.length )
				);
			}
		}
	}, [ defaultValue ] );

	const handleInsertHTML = () => {
		if ( customHTML ) {
			const quill = quillRef.current;
			const range = quill.getSelection( true );
			quill.insertEmbed( range.index, 'customHTML', customHTML, 'user' );
			isShowCustomInserter( false );
			setCustomHTML( '' );
		}
	};

	const handleFileUpload = ( type ) => {
		// eslint-disable-next-line
	let mediaUploader;
		if ( mediaUploader ) {
			mediaUploader.open();
			return;
		}
		const mediaUploaderData = ( fileType ) => {
			switch ( fileType ) {
				case 'image':
					return {
						title: 'Choose Image',
						button: {
							text: 'Choose Image',
						},
						multiple: false,
					};
				case 'pdf':
					return {
						title: 'Choose PDF',
						button: {
							text: 'Choose PDF',
						},
						multiple: false,
					};
				case 'mp3':
					return {
						title: 'Choose Audio',
						button: {
							text: 'Choose Audio',
						},
						multiple: false,
					};
				case 'video':
					return {
						title: 'Choose Video',
						button: {
							text: 'Choose Video',
						},
						multiple: false,
					};

				default:
					return {
						title: 'Choose Image',
						button: {
							text: 'Choose Image',
						},
						multiple: false,
					};
			}
		};
		mediaUploader = window.wp.media( mediaUploaderData( type ) );

		mediaUploader.on( 'select', function () {
			const attachment = mediaUploader
				.state()
				.get( 'selection' )
				.first()
				.toJSON();
			const fileUrl = attachment.url;

			if ( type === 'image' ) {
				insertImageToEditor( fileUrl );
			} else if ( type === 'pdf' ) {
				insertPDFToEditor( fileUrl );
			} else if ( type === 'mp3' ) {
				insertAudioToEditor( fileUrl );
			} else if ( type === 'video' ) {
				insertVideoToEditor( fileUrl );
			}
		} );

		mediaUploader.open();
	};

	const insertImageToEditor = ( url ) => {
		const range = quillRef.current.getSelection();
		quillRef.current.insertEmbed( range.index, 'image', url );
	};

	const insertPDFToEditor = ( url ) => {
		const range = quillRef.current.getSelection();
		quillRef.current.clipboard.dangerouslyPasteHTML(
			range.index,
			`<a href="${ url }" target="_blank">Download PDF</a>`
		);
	};

	const insertVideoToEditor = ( url ) => {
		const range = quillRef.current.getSelection();
		quillRef.current.insertEmbed( range.index, 'customVideo', url );
	};

	const insertAudioToEditor = ( url ) => {
		const range = quillRef.current.getSelection();
		quillRef.current.insertEmbed( range.index, 'customAudio', url );
	};

	return (
		<React.Fragment>
			<div id={ `editor-container--${ suffix }` }></div>
			<ReactModal
				isOpen={ showCustomInserter }
				onRequestClose={ () => isShowCustomInserter( false ) }
				title={ __( 'Custom HTML', 'quizpress' ) }
				suffix="custom-html"
				size="medium"
			>
				<div className="quizpress-custom-editor-controls">
					<textarea
						cols="50"
						rows="5"
						value={ customHTML }
						onChange={ ( e ) => setCustomHTML( e.target.value ) }
						placeholder={ __( 'Enter HTML content', 'quizpress' ) }
					/>
					<Button
						label={ __( 'Add to editor', 'quizpress' ) }
						onClick={ handleInsertHTML }
					/>
				</div>
			</ReactModal>
		</React.Fragment>
	);
}
