
import { Command } from '@ckeditor/ckeditor5-core';
import { Collection, first } from '@ckeditor/ckeditor5-utils';
import * as QMSCKEditorConstant from '../common/qmsCKEditorConstant';
import * as QMSCKEditorEnum from '../common/qmsCKEditorEnum';
import * as QMSCKEditorService from '../common/qmsCKEditorService';
import { isImageAllowed, isLinkElement} from './utils';
import AutomaticDecorators from './utils/automaticdecorators';
import * as QMSCKEditorUtil from '../common/qmsCKEditorUtil';

 export default class LinkDialogCommand extends Command {
    constructor( editor ) {
		super( editor );
		this.manualDecorators = new Collection();
		this.automaticDecorators = new AutomaticDecorators();
	}
 
	restoreManualDecoratorStates() {
		for ( const manualDecorator of this.manualDecorators ) {
			manualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );
		}
	}
 
	refresh() {
		const model = this.editor.model;
		const doc = model.document;

		const selectedElement = first( doc.selection.getSelectedBlocks() );

		// A check for the `LinkImage` plugin. If the selection contains an element, get values from the element.
		// Currently the selection reads attributes from text nodes only. See #7429 and #7465.
		if ( isImageAllowed( selectedElement, model.schema ) ) {
			this.value = selectedElement.getAttribute( 'linkHref' );
			this.isEnabled = model.schema.checkAttribute( selectedElement, 'linkHref' );
		} else {
			this.value = doc.selection.getAttribute( 'linkHref' );
			this.isEnabled = model.schema.checkAttributeInSelection( doc.selection, 'linkHref' );
		}

		for ( const manualDecorator of this.manualDecorators ) {
			manualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );
		}
	}
  
     execute() {
        const editor = this.editor;
        const model = editor.model;
        const selection = model.document.selection;
        const ranges = selection.getFirstRange();

        let link = QMSCKEditorEnum.hyperLink;

		let parentLink = this._getSelectedLinkElement();

		if(parentLink) {				
			let linkOption = parentLink.getAttribute('url') || parentLink.getAttribute('option');
			link.typeId = QMSCKEditorUtil.getLinkType(linkOption);
			link.targetId = parentLink.getAttribute('target') ? QMSCKEditorEnum.targetEnum[parentLink.getAttribute('target')] : 0;
			if (parentLink._children.length > 0) {
				link.title = parentLink._children[0]._textData ? parentLink._children[0]._textData.trim() : '';
			}
			else {
				link.title = '';
			}
			link.protocolId = QMSCKEditorUtil.getProtocolId(linkOption);
			link.url = parentLink.getAttribute('href') || '';
			link.edit = true;
			link.ckeditorId = editor.id;
		} else {
			link.typeId = 0;
			link.targetId = 0;
			link.protocolId = 0;
			link.url = '';
			link.title = '';
			link.editorContent = '';
			link.ckeditorId = editor.id;
			for (const item of ranges.getItems()) {
				if (item.data) {
					link.title = item.data;
				}
			}
		}

        QMSCKEditorService.linkNotify(link);
        window[QMSCKEditorConstant.QMSCK_LINKED] = false;
        window.addEventListener(QMSCKEditorConstant.QMSCK_LINK_PLUGIN_RESP, function(evt) {
					if (window[QMSCKEditorConstant.QMSCK_LINKED]){
							return;
					}
					window[QMSCKEditorConstant.QMSCK_LINKED] = true;
					const options = evt.detail;
					// Return options = null when user cancel link dialog instead of not returning anything to avoid redundant event listener
					if (options) {
						editor.commands.get('link').execute(options);
					}
        }, { once: true });
     }

     _getDecoratorStateFromModel( decoratorName ) {
		const model = this.editor.model;
		const doc = model.document;
		const selectedElement = first( doc.selection.getSelectedBlocks() );

		// A check for the `LinkImage` plugin. If the selection contains an element, get values from the element.
		// Currently the selection reads attributes from text nodes only. See #7429 and #7465.
		if ( isImageAllowed( selectedElement, model.schema ) ) {
			return selectedElement.getAttribute( decoratorName );
		}

		return doc.selection.getAttribute( decoratorName );
	}

	_getSelectedLinkElement() {
		const view = this.editor.editing.view;
		const selection = view.document.selection;

		if ( selection.isCollapsed ) {
			return findLinkElementAncestor( selection.getFirstPosition() );
		} else {
			// The range for fully selected link is usually anchored in adjacent text nodes.
			// Trim it to get closer to the actual link element.
			const range = selection.getFirstRange().getTrimmed();
			const startLink = findLinkElementAncestor( range.start );
			const endLink = findLinkElementAncestor( range.end );

			if ( !startLink || startLink != endLink ) {
				return null;
			}

			// Check if the link element is fully selected.
			if ( view.createRangeIn( startLink ).getTrimmed().isEqual( range ) ) {
				return startLink;
			} else {
				return null;
			}
		}
	}

 }

 function findLinkElementAncestor( position ) {
	return position.getAncestors().find( ancestor => isLinkElement( ancestor ) );
}
