var FR = {
	UI: {},
	changesSaved: true,
	init() {
		Ext.get('loadMsg').fadeOut();
		Ext.getBody().mask('Loading image..');
		this.UI.tbar = new Ext.Toolbar({
			cls: 'fr-viewport-top-bar',
			items: [
				'->',
				{
					iconCls: 'fa-lg fa-crop-alt',
					id: 'cropToggle',
					tooltip: 'Crop',
					enableToggle: true,
					toggleHandler: (btn, pressed) => {
						this.editor[pressed ? 'crop' : 'clear']();
						this.UI.applyMenu.setVisible(pressed);
					}
				},
				{
					xtype: 'tbtext',
					id: 'resolution',
					text: ''
				},
				{
					iconCls: 'fa-lg fa-expand-alt',
					tooltip: 'Scale down',
					id: 'scaleToggle',
					enableToggle: true,
					toggleHandler: (btn, pressed) => {
						this.UI.scaleMenu.setVisible(pressed);
					}
				},
				'-',
				{
					iconCls: 'fa-lg fa-redo',
					tooltip: 'Rotate',
					menu: {
						modal: false,
						items: [
							{
								iconCls: 'fa-undo',
								text: '90&deg;',
								handler() {
									this.editor.rotate(-90);
									return false;
								}, scope: this
							},
							{
								iconCls: 'fa-redo',
								text: '90&deg;',
								handler() {
									this.editor.rotate(90);
									return false;
								}, scope: this
							},
							{
								text: '1&deg;',
								iconCls: 'fa-empty',
								handler: ()=> false,
								menu: {
									modal: false,
									focusEnabledItems: false,
									items: [
										{
											xtype: 'slider',
											vertical: true,
											height: 200,
											style: 'margin:var(--theme-menu-padding)',
											value: 0,
											minValue: -90,
											maxValue: 90,
											listeners: {
												drag(s, newValue) {
													this.editor.rotateTo(newValue);
												},
												scope: this
											}
										}
									],
									listeners: {
										show(menu) {
											var slider = menu.items.items[0];
											var editorData = this.editor.getData();
											var currentRoateAngle = editorData.rotate;
											slider.setMinValue(currentRoateAngle-90);
											slider.setMaxValue(currentRoateAngle+90);
											slider.setValue(currentRoateAngle);
										}, scope: this
									}
								}
							},
							'-',
							{
								iconCls: 'fa-times',
								text: 'Reset',
								handler: () => this.editor.rotateTo(0)
							}
						]
					}
				},
				{
					iconCls: 'fa-lg fa-adjust',
					tooltip: 'Adjust',
					menu: [
						{
							text: 'Brightness',
							iconCls: 'fa-lg fa-sun',
							handler: () => this.imageControl('Brightness', 'brightness')
						},
						{
							text: 'Contrast',
							iconCls: 'fa-lg fa-adjust',
							handler: () => this.imageControl('Contrast', 'contrast')
						},
						{
							text: 'Saturation',
							iconCls: 'fa-lg fa-tint',
							handler: () => this.imageControl('Saturation', 'saturation')
						},
						{
							text: 'Sharpen',
							iconCls: 'fa-lg fa-eye',
							handler: () => this.imageControl('Sharpen', 'sharpen')
						}
					]
				},
				{
					iconCls: 'fa-lg fa-arrows-h',
					tooltip: 'Flip horizontal',
					handler: ()=> {
						this.editor.scaleX(-this.editor.getData().scaleX);
					}
				},
				{
					iconCls: 'fa-lg fa-arrows-v',
					tooltip: 'Flip vertical',
					handler: () => {
						this.editor.scaleY(-this.editor.getData().scaleY);
					}
				},
				'->'
			]
		});
		new Ext.Viewport({
			items: {
				tbar: {
					cls: 'fr-viewport-top-bar',
					items: [
						{
							text: Ext.isMobile ? false : "Save",
							iconCls: Ext.isMobile ? 'fa-save' : false,
							cls: 'fr-btn-primary',
							hidden: FR.vars.saveURL === undefined,
							handler: () => this.save(false)
						},
						{
							text: "Save and close",
							cls: 'fr-btn-primary',
							hidden: (FR.vars.saveURL === undefined) || Ext.isMobile,
							handler: () => this.save(true)
						},
						{
							text: "Close",
							hidden: !FR.vars.windowId,
							handler: () => FR.tryToCloseWindow()
						},
						{
							xtype: 'tbtext',
							id: 'status',
							text: ''
						},
						'->',


						{
							iconCls: 'fa-lg fa-compress',
							tooltip: 'Fit to screen',
							handler: ()=> {
								this.editor.reset();
								this.fitToScreen();
							}
						},
						{
							xtype: 'tbtext',
							id: 'zoomStatus',
							text: ''
						},
						{
							iconCls: 'fa-lg fa-expand',
							tooltip: 'Full size',
							handler: ()=> this.editor.zoomTo(1)
						},
						'->',
						{
							text: Ext.isMobile ? false : "Reload image",
							tooltip: Ext.isMobile ? 'Reload image': false,
							cls: 'fr-btn-secondary',
							iconCls: 'fa-refresh',
							handler: () => this.editor.replace(FR.vars.imageURL)
						}
					]
				},
				html: '<div id="editor" class="cropperEditor"></div>',
				bbar: this.UI.tbar
			},
			monitorResize: true,
			listeners: {
				resize() {
					var ed = this.editor;
					if (ed.ready) {
						window.setTimeout(() => {
							ed.resize();
							ed.reset();
						}, 200);
					}
				},
				afterrender() {
					this.status = Ext.c('status');
					var image = Ext.DomHelper.append('editor', {
						tag: 'img',
						src: FR.vars.imageURL,
						class: 'cropperSource'
					});

					this.editor = new Cropper(image, {
						viewMode: 1,
						autoCrop: false,
						dragMode: 'move',
						highlight: false,
						toggleDragModeOnDblclick: false,
						ready() {
							Ext.getBody().unmask();
							var imageData = FR.editor.getImageData();
							Ext.get('resolution').update(
								imageData.naturalWidth+
								' <i class="fa fa-times"></i> '+
								imageData.naturalHeight
							);
							FR.editor.zoom(-0.1);
							FR.UI.tbar.doLayout(true);
						},
						crop(e) {
							if (!e.detail.width) {return true;}
							Ext.get('resolution').update(
								Math.round(e.detail.width)+
								' <i class="fa fa-times"></i> '+
								Math.round(e.detail.height)
							);
						},
						zoom(e) {
							Ext.get('zoomStatus').update(Math.round(e.detail.ratio*100)+'%');
						}
					});
				}, scope: this
			}
		});
		this.UI.applyMenu = new Ext.Toolbar({
			floating: true,
			style: 'width: fit-content;padding: var(--theme-menu-padding);',
			anchor: {
				el: FR.UI.tbar.sizingEl,
				align: 'b-t',
				offset: [0, -5]
			},
			keepAnchored: true,
			items: [
				{
					iconCls: 'fa-lg fa-check icon-green',
					id: 'apply',
					text: 'Apply',
					handler: () => this.applyChanges()
				},
				{
					iconCls: 'fa-lg fa-times',
					id: 'cancel',
					text: 'Cancel',
					handler: () => this.cancelChanges()
				}
			]
		});
		this.UI.scaleMenu = new Ext.menu.Menu({
			floating: true,
			modal: false,
			style: 'display:flex;flex-direction: column;gap: var(--theme-menu-padding);',
			anchor: {
				el: this.UI.tbar.sizingEl,
				align: 'b-t',
				offset: [0, -5]
			},
			keepAnchored: true,
			focusEnabledItems: false,
			items: [
				{
					xtype: 'slider',
					id: 'scaleSlider',
					width: 200,
					style: 'margin:var(--theme-menu-padding)',
					decimalPrecision: 2,
					value: 100,
					minValue: 1,
					maxValue: 100,
					listeners: {
						drag: (s, v) => this.scale(v/100)
					}
				},
				{
					xtype: 'toolbar',
					style: 'justify-content:center',
					items: [
						{
							iconCls: 'fa-lg fa-check icon-green',
							text: 'Apply',
							handler: () => {
								this.UI.scaleMenu.hide();
								this.editor.replace(this.editor.getCroppedCanvas().toDataURL());
								Ext.c('scaleSlider').setValue(100);
								Ext.c('scaleToggle').setActive(false, true);
							}
						},
						{
							iconCls: 'fa-lg fa-times',
							text: 'Cancel',
							handler: () => {
								this.UI.scaleMenu.hide();
								this.scale(1);
								Ext.c('scaleToggle').setActive(false, true);
								Ext.c('scaleSlider').setValue(100);
								this.editor.reset();
								this.fitToScreen();
							}
						}
					]
				}
			],
			listeners: {
				show: ()=> {
					this.currentImageData = this.editor.getImageData();
					this.editor.zoomTo(1);
				}
			}
		});
	},
	scale(v) {
		if (this.currentImageData) {
			this.editor.scale(v, v);
			Ext.get('resolution').update(
				Math.round(this.currentImageData.naturalWidth * v)+
				' <i class="fa fa-times"></i> '+
				Math.round(this.currentImageData.naturalHeight * v)
			);
		}
	},
	fitToScreen() {
		var canvasData = this.editor.getCanvasData();
		Ext.get('zoomStatus').update(Math.round(canvasData.width/canvasData.naturalWidth*100)+'%');
	},
	applyChanges() {
		this.UI.applyMenu.hide();
		this.editor.replace(this.editor.getCroppedCanvas().toDataURL());
		Ext.c('cropToggle').setActive(false, true);
	},
	cancelChanges() {
		Ext.c('cropToggle').setActive(false);
		this.UI.applyMenu.hide();
	},
	tryToCloseWindow() {
		if (!FR.changesSaved) {
			new Ext.ux.prompt({
				text: 'Discard the changes made?',
				confirmHandler: () => this.closeWindow()
			});
			return false;
		}
		this.closeWindow();
	},
	closeWindow() {
		if (window.parent) {
			if (FR.vars.windowId) {
				return window.parent.FR.UI.popups[FR.vars.windowId].close();
			}
			with (window.parent) {
				if (FR.UI.FileViewer?.isVisible()) {
					return FR.UI.FileViewer.hide();
				}
			}
		}
		window.close();
	},
	save(close) {
		this.closeAfterSave = close;
		var canvas = this.editor.getCroppedCanvas();
		canvas.toBlob(function(blob) {
			FlowUtils.simpleUpload({
				cacheid: FR.vars.cacheid,
				urlRoot: FR.vars.URLRoot,
				target: FR.vars.saveURL,
				debug: FR.vars.devMode,
				csrf: FR.vars.csrf_token,
				flowOpts: {
					chunkSize: FR.vars.UploadChunkSize
				},
				query: FR.vars.uploadQuery,
				files: [FileRunFile.fromBlob(blob, {name: FR.vars.saveFileName})],
				onProgress: (msg, flow) => {
					FR.status.update(msg);
				},
				onFailure: (msg) => {
					new Ext.ux.prompt({text: msg});
				},
				onSuccess: (msg) => {
					FR.changesSaved = true;
					if (FR.vars.windowId) {
						FR.status.update('');
						window.parent.FR.UI.feedback(msg, 'success');
					} else {
						FR.status.update(msg);
					}
					FR.UI.tbar.doLayout(true);
					if (FR.closeAfterSave) {
						FR.closeWindow();
					}
				}
			});
		}, FR.vars.saveMimeType);
	},
	imageControl(title, method) {
		FR.bWin = new Ext.Window({
			title: title,
			modal: true,
			closable: false,
			destroyAfterHide: true,
			items: [
				{
					height: 300,
					width: 400,
					bodyStyle: 'position: relative;display: flex;align-items: center;justify-content: center;'
				},
				{
					xtype: 'toolbar',
					style: 'margin-top: var(--pad)',
					items: [
						{
							xtype: 'slider',
							width: '100%',
							value: 0,
							minValue: -50,
							maxValue: 50,
							listeners: {
								changecomplete: function (s, newValue) {
									FR.bWin.cam.revert(false);
									FR.bWin.cam[FR.bWin.camanMethod](newValue);
									FR.bWin.cam.render();
								}, scope: this
							}
						}
					]
				}
			],
			camanMethod: method,
			bbar: {
				items: [{
					cls: 'fr-btn-primary',
					text: 'Apply',
					handler() {
						FR.editor.replace(FR.bWin.canvas.dom.toDataURL('image/jpeg'));
						FR.bWin.close();
					}
				},
				{
					text: 'Cancel',
					handler: () => FR.bWin.close()
				}]
			},
			listeners: {
				'show': (w) => {
					var ct = w.items.first().body,
						c = FR.editor.getCroppedCanvas();
					c.removeAttribute('id');
					w.canvas = ct.insertFirst(c);
					w.canvas.dom.setAttribute('data-caman-hidpi-disabled', '1');

					var image = FR.editor.image;

					var boxWidth = ct.getWidth();
					var boxHeight= ct.getHeight();

					if (image.width > image.height) {
						if (image.width > boxWidth) {
							w.canvas.setWidth(boxWidth);
						} else {
							w.canvas.setHeight(boxHeight);
						}
					} else {
						if (image.height > boxHeight) {
							w.canvas.setHeight(boxHeight);
						} else {
							w.canvas.setWidth(boxWidth);
						}
					}
					w.cam = Caman(w.canvas.dom);
				}
			}
		});
	}
};
Ext.onReady(() => FR.init());