/**
 * @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
 */

/**
* @module easy-image/cloudservicesuploadadapter
*/

import { Plugin } from '@ckeditor/ckeditor5-core';
import { FileRepository, type FileLoader, type UploadAdapter } from '@ckeditor/ckeditor5-upload';
import { CloudServices, type CloudServicesCore, type UploadGateway, type FileUploader } from '@ckeditor/ckeditor5-cloud-services';

/**
 * A plugin that enables upload to [CKEditor Cloud Services](https://ckeditor.com/ckeditor-cloud-services/).
 *
 * It is mainly used by the {@link module:easy-image/easyimage~EasyImage} feature.
 *
 * After enabling this adapter you need to configure the CKEditor Cloud Services integration through
 * {@link module:cloud-services/cloudservicesconfig~CloudServicesConfig `config.cloudServices`}.
 */
export class CloudServicesUploadAdapter extends Plugin {
	private _uploadGateway?: UploadGateway;

	/**
	 * @inheritDoc
	 */
	public static get pluginName() {
		return 'CloudServicesUploadAdapter' as const;
	}

	/**
	 * @inheritDoc
	 */
	public static override get isOfficialPlugin(): true {
		return true;
	}

	/**
	 * @inheritDoc
	 */
	public static get requires() {
		return [ CloudServices, FileRepository ] as const;
	}

	/**
	 * @inheritDoc
	 */
	public init(): void {
		const editor = this.editor;

		const cloudServices = editor.plugins.get( CloudServices );

		const token = cloudServices.token;
		const uploadUrl = cloudServices.uploadUrl;

		if ( !token ) {
			return;
		}

		const cloudServicesCore: CloudServicesCore = editor.plugins.get( 'CloudServicesCore' );
		this._uploadGateway = cloudServicesCore.createUploadGateway( token, uploadUrl! );

		editor.plugins.get( FileRepository ).createUploadAdapter = loader => {
			return new Adapter( this._uploadGateway!, loader );
		};
	}
}

class Adapter implements UploadAdapter {
	private uploadGateway: UploadGateway;
	private loader: FileLoader;
	private fileUploader?: FileUploader;

	constructor( uploadGateway: UploadGateway, loader: FileLoader ) {
		this.uploadGateway = uploadGateway;

		this.loader = loader;
	}

	public upload() {
		return this.loader.file.then( file => {
			this.fileUploader = this.uploadGateway.upload( file! );

			this.fileUploader.on( 'progress', ( evt, data ) => {
				this.loader.uploadTotal = data.total;
				this.loader.uploaded = data.uploaded;
			} );

			return this.fileUploader.send();
		} );
	}

	public abort() {
		this.fileUploader!.abort();
	}
}
