var FileBrowser = {
	storage_methods: ['ftp','store'],
	fetcher: {
		urls: {
			ftp: '/admin/stored_files/ftp',
			store: '/admin/stored_files/browse'
		},
		directory: function(on, directory, callback, loading_element) {
			this.fetchJSON(this.urls[on],{'dir': directory},callback,loading_element);
		},
		fetchJSON: function(url,parameters,callback,loading_element) {
			new Ajax.Request(url, { method: 'get', parameters:parameters, evalScripts:true, 
						onSuccess: function(or) {  return callback(or.responseText.evalJSON()); }, 
						onLoading: function (or) { $(loading_element).show();},
						onLoaded: function(or) { $(loading_element).hide();} });
		}
	},
	closeAllMenus: function() {
		$$('.'+FileBrowser.File.prototype.menu_class).each(Element.hide);
	},
	insertTopLevel: function(el) {
		document.getElementsByTagName('body')[0].appendChild(el);
	} 
}

FileBrowser.Browser = Class.create({
	selector_template: 'file_selector_#{id}',
	setter_template: 'file_browser_setter_#{id}',
	browser_template: '#{on}_browser_#{id}',
	browse_toggle_template: 'file_selector_browse_toggle_#{id}',
	file_browser_class: 'file_browser',
	browsers: {},
	initialize: function(id) {
		this.id = id;
		this.element = this.el('selector');
		this.tabs = new Tabs(this.el('setter').id);
		this.el('browse_toggle').observe('click',this.toggleSetter.bindAsEventListener(this));
		FileBrowser.storage_methods.each(function(storage_method,i) {
			var pane = i + 1;
			var browser_element = new Element('div', {'class':this.file_browser_class,'id':this.browser_template.interpolate({on:storage_method,id:this.id})});
			this.tabs.getPane(pane).insert(browser_element);
			this.browsers[storage_method] = new FileBrowser.Directory(storage_method,'','',browser_element.id);
			this.tabs.getTab(pane).observe('click', function () {
				this.browsers[storage_method].open(true);
			}.bind(this));
		}.bind(this));
		this.browsers[FileBrowser.storage_methods.first()].open();
	},
	toggleSetter: function() {
		this.el('selector').toggleClass('selector_open');
		this.el('setter').toggle()
		if (this.el('setter').visible()) Intersect.scrollTo(this.el('setter'));
		this.el('browse_toggle').toggleValue('Browse','Close');
	},
	el: function(element_name) {
		return $(this[element_name + '_template'].interpolate({id:this.id}));
	}
});


FileBrowser.Selector = Class.create({
	selector_template: 'file_selector_#{id}',
	setter_template: 'file_browser_setter_#{id}',
	browser_template: '#{on}_browser_#{id}',
	current_template: 'file_browser_current_#{id}',
	form_template: 'file_selector_form_#{id}',
	browse_toggle_template: 'file_selector_browse_toggle_#{id}',
	file_browser_class: 'file_browser',
	multiple: true,
	current_files: [],
	browsers: {},
	initialize: function(id, name, method, current_file, options) {
		this.id = id;
		this.name = name;
		this.method = method;
		// // console.log('initialize', this.id, this.current_files);
		this.current_files = [];
		this.element = this.el('selector');
		if (options.multiple != undefined) this.multiple = options.multiple; 
		this.tabs = new Tabs(this.el('setter').id);
		this.el('browse_toggle').observe('click',this.toggleSetter.bindAsEventListener(this));
		FileBrowser.storage_methods.each(function(storage_method,i) {
			var pane = i + 1;
			var browser_element = new Element('div', {'class':this.file_browser_class,'id':this.browser_template.interpolate({on:storage_method,id:this.id})});
			this.tabs.getPane(pane).insert(browser_element);
			this.browsers[storage_method] = new FileBrowser.Directory(storage_method,'','',browser_element.id);
			this.tabs.getTab(pane).observe('click', this.browsers[storage_method].open.bindAsEventListener(this.browsers[storage_method]));
		}.bind(this));
		if (current_file != undefined) this.setCurrent(current_file);
		$(this.element).observe('file:selected',function(e) {
			this.setCurrent(e.memo.file);
		}.bind(this));
		$(this.element).observe('file:remove',function(e) {
			this.removeCurrent(e.memo.file);
		}.bind(this));
	},
	setCurrent: function(file) {
		if (Object.isArray(file)) {
			file.each(function(a_file) {
				this.setCurrent(a_file);
			}.bind(this));
			this.makeSortable();
			return;
		}
		var current_holder = $(this.el('current'));
		var list = current_holder.down('ul');
		var current_file = new FileBrowser.File(this.id, file,true);
		if (this.multiple) {
			this.current_files.push(current_file);
			list.insert(current_file.toElement('current_file_' + current_file.id));
			current_holder.show();
			this.updateForm();
		} else {
			list.update(current_file.toElement('current_file_' + current_file.id));
			current_holder.show();
			this.current_files[0] = current_file;
			this.updateForm();
		}
		// // console.log('set current');
		// // console.log('this', this);
		// // console.log('current_files',this.current_files);
	},
	removeCurrent: function(file) {
		file.file_element.remove();
		file.form_element.remove();
		// console.log("before_remove: ", this.current_files);
		this.current_files = this.current_files.reject(function (f) { return f == file });
		// console.log("after_remove: ", this.current_files);
		// remove the form element too
		if (this.multiple) {
			this.makeSortable();
		}
		this.updateForm();
	},
	updateForm: function() {
			// console.log("updateForm: ",this.current_files);
		$(this.el('form')).update("");
		if (this.current_files.length == 0) {
			$(this.el('form')).insert(this.blankFormElement());
		} else {
			$A(this.current_files).each(function(file, i) {
			var num = this.multiple ? i + 1 : undefined;
			var form_el = file.toFormElement(this.name,this.method,num);
			$(this.el('form')).insert(form_el);
		}.bind(this));
		}
	},
	toggleSetter: function() {
		this.el('selector').toggleClass('selector_open');
		this.browsers[FileBrowser.storage_methods.first()].open();
		this.el('setter').toggle()
		if (this.el('setter').visible()) Intersect.scrollTo(this.el('selector'));
		this.el('browse_toggle').toggleValue('Browse','Close');
	},
	makeSortable: function() {
		var current_holder = $(this.el('current'));
		var list = current_holder.down('ul');
		var update = function() { this.sortCurrent(Sortable.sequence(list)); }.bind(this);
		var sortable = Sortable.create(list, {tag: 'li', onChange: update, tree: false});
	},
	updateSortable: function() {
		
	},
	sortCurrent: function(sort_order) {
		var new_order = [];
		// // console.log(sort_order)
		sort_order.each(function(file_id) {
			new_order.push(this.getCurrentFileByFileId(file_id));
		}.bind(this));
		// // console.log(new_order);
		this.current_files = new_order;
		this.updateForm();
	},
	getCurrentFileByFileId: function(file_id) {
		return this.current_files.find(function(file) {
			return file.id == file_id;
		});
	},
	blankFormElement: function() {
		var file = new FileBrowser.File('form', {id: '', source: 'store'});
		// console.log('blank_file', file);
		var num = this.multiple ? "0" : undefined;
		var form_el = file.toFormElement(this.name,this.method, num);
		// console.log('blank_form_el', form_el);
		return form_el;
	},
	el: function(element_name) {
		return $(this[element_name + '_template'].interpolate({id:this.id}));
	}
});

FileBrowser.Directory = Class.create({
	directories: [],
	files: [],
	is_open: false,
	is_loaded: false,
	initialize: function(src, parent, name, parent_element) {
		this.src = src;
		this.name = name;
		this.parent = parent;
		if (parent_element != undefined) this.parent_element = $(parent_element);
		this.loading_image = new Element('img',{src:'/images/admin/file_browser/icon_loading.gif','class':'directory_loading'}).hide();
	},
	toggle: function() {
		if (this.is_open) {
			this.close();
		} else {
			this.open();
		}
	},
	open: function(force) {
		if (force == undefined) force = false;
		this.is_open = true;
		if (!this.is_loaded || force) {
			this.load();
		} else {
			this.sub_element.show();
		}
		return this.element;
	},
	close: function() {
		this.sub_element.hide();
		this.is_open = false;
	},
	load: function () {
		FileBrowser.fetcher.directory(this.src, this.path(),
			function (dir_structure) {
				this.directories = dir_structure.directories.collect(function(d) { return new FileBrowser.Directory(this.src,this.path(),d);}.bind(this));
				this.files = [];
				dir_structure.files.each(function(f) { this.files.push(new FileBrowser.File(this.toString(), f)); }.bind(this));
				this.is_loaded = true;
				this.insert();
			}.bind(this), this.loading_image);
	},
	icon: function() {
		return new Element('span').addClassName('file_icon').addClassName('icon_directory');
	},
	path: function() {
		return this.parent + "/" + this.name;
	},
	toElement: function() {
		if (this.name != "") {
			this.link 	= new Element('a').addClassName('directory_link').insert(this.icon()).insert(this.name).insert(this.loading_image);
			this.link.observe('click',function (e) { this.click(); return false; }.bind(this));
		}
	 	if (!this.element) { this.element = new Element('li').addClassName('directory').update(this.link) };
		if (this.is_open) {
			var directory_list = new Element('ul').addClassName('directory_list');
			this.directories.each(function (d) {
				directory_list.insert({bottom: d.toElement()});
			}.bind(this));
			this.files.each(function (f) {
				directory_list.insert({bottom: f.toElement()}); //});
			}.bind(this));
			if ($(this.sub_element)) {
				this.sub_element.replace(directory_list);
			} else {
				this.sub_element = directory_list;
				this.element.insert({bottom:this.sub_element});
			}
		}
		return this.element;
	},
	insert: function() {
		if ($(this.parent_element)) {
			this.parent_element.insert({bottom:this.toElement()});
		} else {
			this.element.replace(this.toElement());
		}
	},
	click: function() {
		FileBrowser.closeAllMenus();
		this.toggle();
	}
	
});

FileBrowser.File = Class.create({
	menu_open: false,
	menu_class: 'file_menu',
	selected: false,
	initialize: function(namespace, file_structure, selected) {
		this.namespace		=	namespace;
		this.id 				= file_structure.id;
		this.filename 	= file_structure.filename;
		this.type				= file_structure.type;
		this.url				= file_structure.url;
		this.source   	= file_structure.source;
		this.size				= file_structure.size;
		this.dimensions = file_structure.dimensions;
		this.resize_type= file_structure.resize_type;
		this.full_path= file_structure.full_path;
		if (selected != undefined) this.selected = selected;
	},	
	icon: function() {
		if (!$(this.icon_element)) {
			this.icon_element = '<span class="file_icon icon_file_' + this.type + '">&nbsp;</span>';
/*			new Element('span').addClassName('file_icon').addClassName('icon_file_'+this.type).update('&nbsp;');*/
		}
		return this.icon_element;
	},
	toElement: function(id) {
		if (id == undefined) { id = "file_" + this.namespace + '_' + id; }
		else { id = this.namespace + '_' + id; }
		this.link_element = new Element('a').insert(this.icon() + this.toString());
		this.file_element = new Element('li', {'id': id}).addClassName('file').insert(this.link_element);
		this.link_element.observe('click', this.click.bindAsEventListener(this));
		return this.file_element;
	},
	toFormElement: function(name, method, num) {
		var form_name = "";
		var form_num = "";
		if (num != undefined && num) { form_num = "["+ num +"]";}
		if (this.source == 'ftp') {
			form_name = "#{name}[#{method}]#{form_num}[move_file]".interpolate({name:name,form_num:form_num,method:method});
			this.form_element = new Element('input',{'type':'hidden','name':form_name,'value':this.full_path});
		} else if (this.source == 'store') {
			form_name = "#{name}[#{method}]#{form_num}".interpolate({name:name,form_num:form_num, method:method});
			this.form_element = new Element('input',{'type':'hidden','name':form_name,'value':this.id});
		}
		return this.form_element;
	},
	toString: function() {
		var str = this.filename;
		var meta = "";
		if (this.resize_type != undefined) { meta += this.resize_type; }
		if (this.size				 != undefined) { meta += ":" + this.size; }
		if (this.dimensions  != undefined) { meta += " " + this.dimensions; }
		if (meta != "") { meta = " <em>(" + meta + ")</em>";}
		return str + meta;
	},
	buildMenu: function() {
		if (!$(this.menu_element)) {
			var menu = new Element('ul').addClassName(this.menu_class).hide();
			$H(FileBrowser.FileActions).each(function(action) {
				var link = new Element('a').update(action.value.text);
				var menu_item = new Element('li').addClassName('file_menu_item').insert(link);
				if (action.value.enabled(this)) {
					link.observe('click',action.value.execute.bindAsEventListener(this));
				} else {
					link.addClassName('disabled');
				}
				menu.insert(menu_item);
			}.bind(this));
			this.menu_element = menu;
		}
		return this.menu_element;
	},
	setMenuPosition: function(x,y) {
		this.menu_element.setStyle({position:'absolute',left: x + 10 + 'px',top: y + 5 + 'px'});
	},
	click: function(e) {
		FileBrowser.insertTopLevel(this.buildMenu());
		this.toggleMenu(e);
	},
	toggleMenu: function(e) {
		if (this.menu_open) {
			this.closeMenu(e);
		} else {
			this.openMenu(e);
/*			this.makeSelected();*/
		}
	},
	openMenu: function(e) {
		FileBrowser.closeAllMenus();
		this.menu_open = true;
		var offset = this.file_element.positionedOffset();
		this.setMenuPosition(e.pointerX(),e.pointerY());
		this.menu_element.show();
	},
	closeMenu: function(e) {
		this.menu_element.hide();
		this.menu_open = false;
	},
	makeSelected: function() {
		this.link_element.addClassName('selected');
	},
	destroy: function() {
		new Ajax.Request('/admin/stored_files/'+this.id, { method: 'delete'});
	}
});

FileBrowser.FileActions = {
	preview: {
		text: "Preview",
		execute: function(e) {
			return window.open(this.url,this.filename,"height=800,width=600,status=no,toolbar=no,menubar=no,location=no");
		},
		enabled: function(file) {
			return !!file.url;
		}
	},
	copy: {
		text: "Copy URL",
		execute: function(e) {
			Intersect.copyTextToClipboard(this.url);
			this.closeMenu(e);
		},
		enabled: function(file) {
			return !!file.url;
		}
	},
	image: {
		text: "Copy IMG",
		execute: function(e) {
			var image_template = '<img src="#{url}" alt="#{alt}" />';
			Intersect.copyTextToClipboard(image_template.interpolate({url: this.url, alt: this.filename}));
			this.closeMenu(e);
		},
		enabled: function(file) {
			return !!file.url && file.url.match(/(jpg|png|gif)$/i);
		}
	},
	select: {
		text: "Select",
		execute: function(e) {
			this.file_element.fire('file:selected',{file:this});
			this.closeMenu(e);
		},
		enabled: function(file) {
			return !file.selected;
		}
	},
	remove: {
		text: "Remove",
		execute: function(e) {
			this.file_element.fire('file:remove',{file:this});
			this.closeMenu(e);
		},
		enabled: function(file) {
			return !!file.selected;
		}
	},
	destroy: {
		text: "Delete",
		execute: function(e) {
			if (confirm('Are you sure you want to delete this file? There is no undo.')) {
				this.destroy();
				this.file_element.remove();
				this.closeMenu(e);
			}
		},
		enabled: function(file) {
			return !!file.id;
		}
	},
	close: {
		text: "Close Menu",
		execute: function(e) {
			this.closeMenu(e);
		},
		enabled: function(file) {
			return true;
		}
	}
}


var Tabs = Class.create();
Tabs.prototype = {
	initial_tab: 1,
	current_tab: 1,
	
	initialize: function(identitfier) {
		this.identifier = identitfier;
		this.current_tab = this.initial_tab;
		this.initializeTabs();
	},
	
	selectTab: function(num) {
		this.getPane(this.current_tab).hide();
		this.getTab(this.current_tab).removeClassName('selected');
		this.current_tab = num;
		this.getPane(this.current_tab).show();
		this.getTab(this.current_tab).addClassName('selected');
	},
	
	getPanes: function() {
		return $(this.identifier + '_panes').select('.pane');
	},
	getPane: function(num) {
		return $(this.identifier + '_panes_pane_' + num);
	},
	getTabs: function() {
		return $(this.identifier + '_tabs').select('.tab');
	},
	getTab: function(num) {
		return $(this.identifier + '_tabs_tab_' + num);
	},
	
	initializeTabs: function() {
		this.getTabs().each(function(el) {
			var tab_id = el.id.replace(this.identifier + '_tabs_tab_','');
			el.onclick = function(elem) {
				this.selectTab(tab_id);
			}.bind(this);
		}.bind(this));
	}
	
}


// FileBrowser.Uploader = {
// 	uploadProgress: {
// 		interval: 2,
// 		form_id: 'upload_form',
// 		frame_id: 'upload_frame',
// 		progress: 0,
// 		initialize: function() {
// 			this.uuid = this.generateUUID();
// 			var form = $(this.form_id);
// 			form.action = form.action + '.txt?X-Progress-ID=' + this.uuid;
// 			form.target = this.iFrame().name;
// 			form.observe('submit', function (e) {
// 				$('submit_button_upload').hide();
// 				$('progress').show();
// 				new PeriodicalExecuter(this.pollProgress.bindAsEventListener(this), this.interval);
// 				// Event.stop(e);
// 			}.bind(this));
// 		},
// 		iFrame: function () {
// 			if (!$(this.frame_id)) {
// 				var frame = new Element('iframe',{'style':"display:none;", 'src':"about:blank", 'name':"uploadframe",'id':this.frame_id});
// 				document.getElementsByTagName('body')[0].appendChild(frame);
// 			}
// 			return $(this.frame_id);
// 		},
// 		pollProgress: function() {
// 			if (!this.checkIframeStatus()) {
// 			new Ajax.Request(
// 				this.nginx_progress_url,
// 				{
// 					method: 'get',
// 					parameters: {
// 						"X-Progress-ID": this.uuid
// 					},
// 					onSuccess: function (oR) {
// 						var upload = oR.responseText.evalJSON();
// 						if (upload.state == 'uploading') {
// 							this.progress = Math.floor((upload.received / upload.size)*100)
// 							this.updateProgressBar();
// 						}
// 					}.bind(this),
// 					onLoading: function (oR) {
// 						this.progress += 1;
// 						this.updateProgressBar();
// 					}.bind(this)
// 				}
// 				);
// 			}
// 		},
// 		updateProgressBar: function () {
// 			if (this.progress > 100) { this.progress = 100; }
// 			$(this.progress_bar_id).style.width = this.progress + '%';
// 			$(this.progress_bar_id).update(this.progress + '%');
// 		},
// 		checkIframeStatus: function() {
// 			var frame = this.iFrame();
// 			var doc = (frame.contentWindow || frame.contentDocument);
// 		  if (doc.document) doc = doc.document;
// 			if (doc.URL != 'about:blank') {
// 				window.location = this.redirect_url;
// 				return true;
// 			}
// 			return false;
// 		},
// 		generateUUID: function () {
// 			var uuid = "";
// 			for (i = 0; i < 32; i++) { uuid += Math.floor(Math.random() * 16).toString(16); }
// 			return uuid;
// 		}
// 	}
// };