Ext.define('PVE.window.UploadToStorage', {
    extend: 'Ext.window.Window',
    alias: 'widget.pveStorageUpload',
    mixins: ['Proxmox.Mixin.CBind'],

    resizable: false,
    modal: true,

    title: gettext('Upload'),

    acceptedExtensions: {
	'import': ['.ova'],
	iso: ['.img', '.iso'],
	vztmpl: ['.tar.gz', '.tar.xz', '.tar.zst'],
    },

    cbindData: function(initialConfig) {
	const me = this;
	const ext = me.acceptedExtensions[me.content] || [];

	me.url = `/nodes/${me.nodename}/storage/${me.storage}/upload`;

	return {
	    extensions: ext.join(', '),
	    filenameRegex: RegExp('^.*(?:' + ext.join('|').replaceAll('.', '\\.') + ')$', 'i'),
	};
    },

    viewModel: {
	data: {
	    size: '-',
	    mimetype: '-',
	    filename: '',
	},
    },

    controller: {
	submit: function(button) {
	    const view = this.getView();
	    const form = this.lookup('formPanel').getForm();
	    const abortBtn = this.lookup('abortBtn');
	    const pbar = this.lookup('progressBar');

	    const updateProgress = function(per, bytes) {
		let text = (per * 100).toFixed(2) + '%';
		if (bytes) {
		    text += " (" + Proxmox.Utils.format_size(bytes) + ')';
		}
		pbar.updateProgress(per, text);
	    };

	    const fd = new FormData();

	    button.setDisabled(true);
	    abortBtn.setDisabled(false);

	    fd.append("content", view.content);

	    const fileField = form.findField('file');
	    const file = fileField.fileInputEl.dom.files[0];
	    fileField.setDisabled(true);

	    const filenameField = form.findField('filename');
	    const filename = filenameField.getValue();
	    filenameField.setDisabled(true);

	    const algorithmField = form.findField('checksum-algorithm');
	    algorithmField.setDisabled(true);
	    if (algorithmField.getValue() !== '__default__') {
		fd.append("checksum-algorithm", algorithmField.getValue());

		const checksumField = form.findField('checksum');
		fd.append("checksum", checksumField.getValue()?.trim());
		checksumField.setDisabled(true);
	    }

	    fd.append("filename", file, filename);

	    pbar.setVisible(true);
	    updateProgress(0);

	    const xhr = new XMLHttpRequest();
	    view.xhr = xhr;

	    xhr.addEventListener("load", function(e) {
		if (xhr.status === 200) {
		    view.hide();

		    const result = JSON.parse(xhr.response);
		    const upid = result.data;
		    Ext.create('Proxmox.window.TaskViewer', {
			autoShow: true,
			upid: upid,
			taskDone: view.taskDone,
			listeners: {
			    destroy: function() {
				view.close();
			    },
			},
		    });

		    return;
		}
		const err = Ext.htmlEncode(xhr.statusText);
		let msg = `${gettext('Error')} ${xhr.status.toString()}: ${err}`;
		if (xhr.responseText !== "") {
		    const result = Ext.decode(xhr.responseText);
		    result.message = msg;
		    msg = Proxmox.Utils.extractRequestError(result, true);
		}
		Ext.Msg.alert(gettext('Error'), msg, btn => view.close());
	    }, false);

	    xhr.addEventListener("error", function(e) {
		const err = e.target.status.toString();
		const msg = `Error '${err}' occurred while receiving the document.`;
		Ext.Msg.alert(gettext('Error'), msg, btn => view.close());
	    });

	    xhr.upload.addEventListener("progress", function(evt) {
		if (evt.lengthComputable) {
		    const percentComplete = evt.loaded / evt.total;
		    updateProgress(percentComplete, evt.loaded);
		}
	    }, false);

	    xhr.open("POST", `/api2/json${view.url}`, true);
	    xhr.send(fd);
	},

	validitychange: function(f, valid) {
	    const submitBtn = this.lookup('submitBtn');
	    submitBtn.setDisabled(!valid);
	},

	fileChange: function(input) {
	    const vm = this.getViewModel();
	    const name = input.value.replace(/^.*(\/|\\)/, '');
	    const fileInput = input.fileInputEl.dom;
	    vm.set('filename', name);
	    vm.set('size', (fileInput.files[0] && Proxmox.Utils.format_size(fileInput.files[0].size)) || '-');
	    vm.set('mimetype', (fileInput.files[0] && fileInput.files[0].type) || '-');
	},

	hashChange: function(field, value) {
	    const checksum = this.lookup('downloadUrlChecksum');
	    if (value === '__default__') {
		checksum.setDisabled(true);
		checksum.setValue("");
	    } else {
		checksum.setDisabled(false);
	    }
	},
    },

    items: [
	{
	    xtype: 'form',
	    reference: 'formPanel',
	    method: 'POST',
	    waitMsgTarget: true,
	    bodyPadding: 10,
	    border: false,
	    width: 400,
	    fieldDefaults: {
		labelWidth: 100,
		anchor: '100%',
            },
	    items: [
		{
		    xtype: 'filefield',
		    name: 'file',
		    buttonText: gettext('Select File'),
		    allowBlank: false,
		    fieldLabel: gettext('File'),
		    cbind: {
			accept: '{extensions}',
		    },
		    listeners: {
			change: 'fileChange',
		    },
		},
		{
		    xtype: 'textfield',
		    name: 'filename',
		    allowBlank: false,
		    fieldLabel: gettext('File name'),
		    bind: {
			value: '{filename}',
		    },
		    cbind: {
			regex: '{filenameRegex}',
		    },
		    regexText: gettext('Wrong file extension'),
		},
		{
		    xtype: 'displayfield',
		    name: 'size',
		    fieldLabel: gettext('File size'),
		    bind: {
			value: '{size}',
		    },
		},
		{
		    xtype: 'displayfield',
		    name: 'mimetype',
		    fieldLabel: gettext('MIME type'),
		    bind: {
			value: '{mimetype}',
		    },
		},
		{
		    xtype: 'pveHashAlgorithmSelector',
		    name: 'checksum-algorithm',
		    fieldLabel: gettext('Hash algorithm'),
		    allowBlank: true,
		    hasNoneOption: true,
		    value: '__default__',
		    listeners: {
			change: 'hashChange',
		    },
		},
		{
		    xtype: 'textfield',
		    name: 'checksum',
		    fieldLabel: gettext('Checksum'),
		    allowBlank: false,
		    disabled: true,
		    emptyText: gettext('none'),
		    reference: 'downloadUrlChecksum',
		},
		{
		    xtype: 'progressbar',
		    text: 'Ready',
		    hidden: true,
		    reference: 'progressBar',
		},
		{
		    xtype: 'hiddenfield',
		    name: 'content',
		    cbind: {
			value: '{content}',
		    },
		},
	    ],
	   listeners: {
		validitychange: 'validitychange',
	   },
	},
    ],

    buttons: [
	{
	    xtype: 'button',
	    text: gettext('Abort'),
	    reference: 'abortBtn',
	    disabled: true,
	    handler: function() {
		const me = this;
		me.up('pveStorageUpload').close();
	    },
	},
	{
	    text: gettext('Upload'),
	    reference: 'submitBtn',
	    disabled: true,
	    handler: 'submit',
	},
    ],

    listeners: {
	close: function() {
	    const me = this;
	    if (me.xhr) {
		me.xhr.abort();
		delete me.xhr;
	    }
	},
    },

    initComponent: function() {
        const me = this;

	if (!me.nodename) {
	    throw "no node name specified";
	}
	if (!me.storage) {
	    throw "no storage ID specified";
	}
	if (!me.acceptedExtensions[me.content]) {
	    throw "content type not supported";
	}

        me.callParent();
    },
});
