FR = {
	initialized: false,
	pgrs: 0,
	duration: 0,
	fileItem: false,
	aurora4M4A: false,
	paused: true,
	volume: 100,
	embedded: false,

	init() {

		Howl.prototype.changeSong = function(o) {
			var self = this;
			self.unload();
			self._duration = 0; // init duration
			self._sprite = {};// init sprite
			self._src = typeof o.src !== 'string' ? o.src : [o.src];
			self._format = typeof o.format !== 'string' ? o.format : [o.format];
			self.load(); // => update duration, sprite(var timeout)
		};

		Ext.get('loadMsg').fadeOut();

		if (this.initialized) {
			return false;
		}
		this.embedded = (Settings.context == 'embedded');

		this.progress = new Ext.Slider({
			region: 'center',
			style: 'flex:1;margin-left: var(--pad)',
			value: 0,
			minValue: 0,
			maxValue: 100,
			decimalPrecision: false,
			showTooltip: true,
			formatToolTipValue(value) {
				if (FR.duration) {
					var seconds = Math.floor(value/100*FR.duration);
					return new Date(seconds * 1000).toISOString().substr(11, 8);
				} else {
					return value+'%';
				}
			},
			listeners: {
				changecomplete(s, newValue) {
					if (this.song) {
						this.song.seek(newValue/100*FR.duration);
					}
				},
				scope: this
			}
		});
		var tbarItems = [
			{
				tooltip: 'Select',
				iconCls: 'fa-check-square',
				handler() {
					window.parent.FR.UI.gridPanel.highlightByRecord(this.fileItem);
				},
				scope: this,
				hidden: !this.embedded
			},
			{
				tooltip: 'Previous',
				style: 'font-size:1.2em',
				iconCls: 'fa-step-backward',
				id: 'fr-prev-btn',
				handler: this.previousFile,
				scope: this,
				disabled: !this.embedded
			},{
				tooltip: 'Play/Pause',
				style: 'font-size:1.5em',
				iconCls: 'fa-play',
				handler: this.playPause,
				id: 'fr-play-btn',
				scope: this
			},{
				tooltip: 'Next',
				style: 'font-size:1.2em',
				id: 'fr-next-btn',
				iconCls: 'fa-step-forward',
				handler: this.nextFile,
				scope: this,
				disabled: !this.embedded
			},
			{
				iconCls: 'fa-volume-up',
				tooltip: 'Adjust Volume',
				menuAlign: 'b-t',
				hidden: Ext.isMobile,
				menu: {
					style: 'padding: var(--theme-menu-padding);display:flex',
					items: [
						{
							xtype: 'slider',
							value: this.volume,
							minValue: 0,
							maxValue: 100,
							showTooltip: true,
							formatToolTipValue: value => value+'%',
							listeners: {
								drag: function (s, newValue) {
									FR.setVolume(newValue);
								}
							}
						}
					]
				}
			},
			this.progress
		];



		FR.playerPanel = new Ext.Window({
			title: '&nbsp;',
			tools: [
				{
					iconCls: 'fa-close',
					tooltip: 'Close',
					handler: () => {
						FR.reset();
						window.parent.FR.UI.AudioPlayer.hide();
					},
					hidden: !this.embedded
				}
			],
			width: 450,
			closable: false,
			draggable: false,
			maximized: this.embedded,
			focusEnabled: false,
			items: {
				xtype: 'toolbar',
				enableOverflow: false,
				items: tbarItems
			}
		});


		this.updater = new Ext.util.DelayedTask(function(){
			FR.setProgress(FR.song.getProgress());
			FR.updateProgress();
			FR.updater.delay(500);
		});
		this.reset();
		if (!this.embedded) {
			this.loadFile(fileItem);
		} else {
			window.parent.FR.UI.AudioPlayer.onLoad(FR);
		}
		this.initialized = true;
	},

	setVolume(v) {
		if (this.song) {
			this.song.setVolume(v);
		}
		this.volume = v;
	},

	playPause() {
		if (this.paused) {
			this.play();
		} else {
			this.pause();
		}
	},

	pause() {
		if (!this.song) {
			return false;
		}
		this.updater.cancel();
		Ext.c('fr-play-btn').setIconClass('fa-play');
		this.song.pause();
		this.paused = true;
	},

	play() {
		if (!this.song) {
			this.nextFile();
		} else {
			this.song.play();
		}
	},

	setProgress(p) {
		FR.pgrs = p;
	},

	setDuration(d) {
		FR.duration = d;
	},

	reset() {
		this.updater.cancel();
		if (this.song) {
			this.song.destroy();
		}
		this.pgrs = 0;
		this.duration = 0;
		FR.playerPanel.setTitle('<span style="color:var(--theme-textLighter);font-style:oblique">'+Ext.T('Play a file')+'</span>');
		this.progress.setValue(0);
	},

	updateProgress() {
		var songTitle = '<span style="color:var(--theme-textLighter);font-size:12px">'+this.fileItem.filename+'</span>';
		var dur;
		if (FR.duration) {
			if (FR.progress.disabled) {
				FR.progress.enable();
			}
			FR.progress.setValue((FR.pgrs / FR.duration * 100), true);
			dur = FR.formatTime(FR.pgrs) + ' / ' + FR.formatTime(FR.duration);
		} else {
			dur = FR.formatTime(FR.pgrs) + ' / &infin;';
			if (!FR.progress.disabled) {
				FR.progress.disable();
			}
		}
		FR.playerPanel.setTitle(dur+' '+songTitle);
	},

	formatTime(s){
		var min=parseInt(s/60);
		var sec=parseInt(s%60);
		return String.leftPad(min,2,'0')+':'+String.leftPad(sec,2,'0');
	},

	loadFile(fileItem) {
		if (fileItem.isFolder || fileItem.filetype != 'mp3') {return false;}
		this.fileItem = fileItem;
		if (this.song) {this.reset();}

		var url = fileItem.url || URLRoot+'/?module=custom_actions&action=audio_player&method=stream&path='+encodeURIComponent(fileItem.path);
		FR.playerPanel.setTitle(Ext.T('Loading %1').replace('%1', fileItem.filename));
		this.song = new Song({
			url: url,
			ext: fileItem.ext,
			volume: this.volume,
			onLoad(duration) {
				FR.setDuration(duration);
				FR.updateProgress();
			},
			onPlay() {
				Ext.c('fr-play-btn').setIconClass('fa-pause');
				FR.paused = false;
				FR.updater.delay(0);
			},
			onLoadError(error) {
				Ext.feedback(Ext.T('Failed to load audio file: %1', error || 'unknown error'));
			},
			onEnd() {
				FR.paused = true;
				Ext.c('fr-play-btn').setIconClass('fa-play');
				if (!Settings.disable_autoplay) {
					FR.nextFile();
				}
			},
			onBuffering(percent) {
				if (percent < 100) {
					FR.playerPanel.setTitle('Loading: ' + Math.round(percent) + '%');
				} else {
					FR.playerPanel.setTitle('');
				}
			},
			onMetadata() {}
		});
		this.play();
	},

	nextFile() {
		if (!window.parent?.FR?.UI?.gridPanel) {return false;}
		var gridStore = window.parent.FR.UI.gridPanel.store;
		var findRecord = this.fileItem;
		var rowIdx = gridStore.findBy(function(record) {
			if (findRecord == record.data) {return true;}
		});
		var nextRowIdx, r;
		if (rowIdx == -1) {
			nextRowIdx = 0;
		} else {
			nextRowIdx = rowIdx+1;
			if (!gridStore.getAt(nextRowIdx)) {
				nextRowIdx = 0;
			}
		}
		r = gridStore.getAt(nextRowIdx);
		if (!r) {return false;}
		this.loadFile(r.data);
	},

	previousFile() {
		var gridStore = window.parent.FR.UI.gridPanel.store;
		var findRecord = this.fileItem;
		var rowIdx = gridStore.findBy(function(record) {
			if (findRecord == record.data) {return true;}
		});
		var prevRowIdx, r;
		if (rowIdx == -1) {
			prevRowIdx = 0;
		} else {
			prevRowIdx = rowIdx-1;
			if (!gridStore.getAt(prevRowIdx)) {
				prevRowIdx = gridStore.data.keys.length-1;
			}
		}
		r = gridStore.getAt(prevRowIdx);
		if (!r) {return false;}
		this.loadFile(r.data);
	}
};

class Song {

	constructor(opts) {
		var aurora = (opts.ext == 'm4a' && FR.aurora4M4A);
		this.opts = opts;
		this.load(aurora);
	}

	load(aurora) {
		this.progress = 0;
		this.duration = 0;
		var ths = this;
		if (aurora) {
			this.aurora = true;
			this.player = AV.Player.fromURL(this.opts.url);
			this.player.volume = this.opts.volume;
			this.player.on('ready', function(){
				ths.duration = Math.ceil(this.duration/1000);
				ths.opts.onLoad(ths.duration);
				ths.opts.onPlay();
			});
			this.player.on('progress', function(p) {ths.progress = Math.ceil(p/1000);});
			this.player.on('error', this.opts.onLoadError.bind(this));
			this.player.on('end', this.opts.onEnd.bind(this));
			this.player.on('metadata', this.opts.onMetadata.bind(this));
			this.player.on('buffer', this.opts.onBuffering.bind(this));

		} else {
			this.aurora = false;
			this.player = new Howl({
				src: [this.opts.url],
				format: [this.opts.ext],
				volume: (this.opts.volume / 100),
				preload: true,
				html5: true,
				onload() {
					ths.opts.onLoad(this.duration());
				},
				onplay: ()=> this.opts.onPlay(),
				onloaderror: () => {
					//retry using aurora
					try {
						FR.aurora4M4A = true;
						this.load(true).play();
					} catch(er) {
						Ext.feedback(Ext.T('Failed to load audio file: %1', er));
					}
				},
				onend() {
					ths.opts.onEnd();
				}
			});
		}
		return this;
	}

	play () {
		this.player.play();
	}

	pause() {
		this.player.pause();
	}

	getDuration() {
		return this.duration;
	}

	getProgress() {
		if (this.aurora) {
			return this.progress;
		}
		return this.player.seek();
	}

	destroy() {
		this.player.stop();
		if (!this.aurora) {
			this.player.unload();
		}
	}

	setVolume(v) {
		if (this.aurora) {
			this.player.volume = v;
		} else {
			this.player.volume(v/100);
		}
	}

	seek(p) {
		this.player.seek(p);
	}
}

Ext.onReady(()=> FR.init());