/**
 * Copyright © Jordan Lee, Dave Perrett, Malcolm Jarvis and Bruno Bierbaumer
 *
 * This file is licensed under the GPLv2.
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */

function PrefsDialog(remote) {

	var data = {
	    dialog: null,
	    remote: null,
	    elements: { },

	    // all the RPC session keys that we have gui controls for
	    keys: [
	        'alt-speed-down',
	        'alt-speed-time-begin',
	        'alt-speed-time-day',
	        'alt-speed-time-enabled',
	        'alt-speed-time-end',
	        'alt-speed-up',
	        'blocklist-enabled',
	        'blocklist-size',
	        'blocklist-url',
	        'dht-enabled',
	        'download-dir',
	        'encryption',
	        'idle-seeding-limit',
	        'idle-seeding-limit-enabled',
	        'lpd-enabled',
	        'peer-limit-global',
	        'peer-limit-per-torrent',
	        'peer-port',
	        'peer-port-random-on-start',
	        'pex-enabled',
	        'port-forwarding-enabled',
	        'rename-partial-files',
	        'seedRatioLimit',
	        'seedRatioLimited',
	        'speed-limit-down',
	        'speed-limit-down-enabled',
	        'speed-limit-up',
	        'speed-limit-up-enabled',
	        'start-added-torrents',
	        'utp-enabled'
	    ],

	    // map of keys that are enabled only if a 'parent' key is enabled
	    groups: {
	        'alt-speed-time-enabled': ['alt-speed-time-begin',
	                                   'alt-speed-time-day',
	                                   'alt-speed-time-end' ],
	        'blocklist-enabled': ['blocklist-url',
	                              'blocklist-update-button' ],
	        'idle-seeding-limit-enabled': [ 'idle-seeding-limit' ],
	        'seedRatioLimited': [ 'seedRatioLimit' ],
	        'speed-limit-down-enabled': [ 'speed-limit-down' ],
	        'speed-limit-up-enabled': [ 'speed-limit-up' ]
	    }
	},

	initTimeDropDown = function(e)
	{
		var i, hour, mins, value, content;

		for (i=0; i<24*4; ++i) {
			hour = parseInt(i/4, 10);
			mins = ((i%4) * 15);
			value = i * 15;
			content = hour + ':' + (mins || '00');
			e.options[i] = new Option(content, value);
		}
	},

	onPortChecked = function(response)
	{
		var is_open = response['arguments']['port-is-open'],
		    text = 'Port is <b>' + (is_open ? 'Open' : 'Closed') + '</b>',
		    e = data.elements.root.find('#port-label');
		setInnerHTML(e[0],text);
	},

	setGroupEnabled = function(parent_key, enabled)
	{
		var i, key, keys, root;

		if (parent_key in data.groups)
		{
			root = data.elements.root,
			keys = data.groups[parent_key];

			for (i=0; key=keys[i]; ++i)
				root.find('#'+key).attr('disabled',!enabled);
		}
	},

	onBlocklistUpdateClicked = function ()
	{
		data.remote.updateBlocklist();
		setBlocklistButtonEnabled(false);
	},
	setBlocklistButtonEnabled = function(b)
	{
		var e = data.elements.blocklist_button;
		e.attr('disabled',!b);
		e.val(b ? 'Update' : 'Updating...');
	},

	getValue = function(e)
	{
		var str;

		switch (e[0].type)
		{
			case 'checkbox':
			case 'radio':
				return e.prop('checked');

			case 'text':
			case 'url':
			case 'email':
			case 'number':
			case 'search':
			case 'select-one':
				str = e.val();
				if( parseInt(str,10).toString() === str)
					return parseInt(str,10);
				if( parseFloat(str).toString() === str)
					return parseFloat(str);
				return str;

			default:
				return null;
		}
	},

	/* this callback is for controls whose changes can be applied
	   immediately, like checkboxs, radioboxes, and selects */
	onControlChanged = function(ev)
	{
		var o = {};
		o[ev.target.id] = getValue($(ev.target));
		data.remote.savePrefs(o);
	},

	/* these two callbacks are for controls whose changes can't be applied
	   immediately -- like a text entry field -- because it takes many
	   change events for the user to get to the desired result */
	onControlFocused  = function(ev)
	{
		data.oldValue = getValue($(ev.target));
	},
	onControlBlurred  = function(ev)
	{
		var newValue = getValue($(ev.target));
		if (newValue !== data.oldValue)
		{
			var o = {};
			o[ev.target.id] = newValue;
			data.remote.savePrefs(o);
			delete data.oldValue;
		}
	},

	getDefaultMobileOptions = function()
	{
		return {
			width: $(window).width(),
			height: $(window).height(),
			position: [ 'left', 'top' ]
		};
	},

	initialize = function (remote)
	{
		var i, key, e, o;

		data.remote = remote;

		e = $('#prefs-dialog');
		data.elements.root = e;

		initTimeDropDown(e.find('#alt-speed-time-begin')[0]);
		initTimeDropDown(e.find('#alt-speed-time-end')[0]);

		o = isMobileDevice
		  ? getDefaultMobileOptions()
		  : { width: 350, height: 400 };
		o.autoOpen = false;
		o.show = o.hide = 'fade';
		o.close = onDialogClosed;
		e.tabbedDialog(o);

		e = e.find('#blocklist-update-button');
		data.elements.blocklist_button = e;
		e.click(onBlocklistUpdateClicked);

		// listen for user input
		for (i=0; key=data.keys[i]; ++i)
		{
			e = data.elements.root.find('#'+key);
			switch (e[0].type)
			{
				case 'checkbox':
				case 'radio':
				case 'select-one':
					e.change(onControlChanged);
					break;

				case 'text':
				case 'url':
				case 'email':
				case 'number':
				case 'search':
					e.focus(onControlFocused);
					e.blur(onControlBlurred);

				default:
					break;
			}
		}
	},

	getValues = function()
	{
		var i, key, val, o={},
		    keys = data.keys,
		    root = data.elements.root;

		for (i=0; key=keys[i]; ++i) {
			val = getValue(root.find('#'+key));
			if (val !== null)
				o[key] = val;
		}

		return o;
	},

	onDialogClosed = function()
	{
		transmission.hideMobileAddressbar();

		$(data.dialog).trigger('closed', getValues());
	};

	/****
	*****  PUBLIC FUNCTIONS
	****/

	// update the dialog's controls
	this.set = function (o)
	{
		var e, i, key, val, option,
		    keys = data.keys,
		    root = data.elements.root;

		setBlocklistButtonEnabled(true);

		for (i=0; key=keys[i]; ++i)
		{
			val = o[key];
			e = root.find('#'+key);

			if (key === 'blocklist-size')
			{
				// special case -- regular text area
				e.text('' + val.toStringWithCommas());
			}
			else switch (e[0].type)
			{
				case 'checkbox':
				case 'radio':
					e.prop('checked', val);
					setGroupEnabled(key, val);
					break;
				case 'text':
				case 'url':
				case 'email':
				case 'number':
				case 'search':
					// don't change the text if the user's editing it.
					// it's very annoying when that happens!
					if (e[0] !== document.activeElement)
						e.val(val);
					break;
				case 'select-one':
					e.val(val);
					break;
				default:
					break;
			}
		}
	};

	this.show = function ()
	{
		transmission.hideMobileAddressbar();

		setBlocklistButtonEnabled(true);
		data.remote.checkPort(onPortChecked,this);
		data.elements.root.dialog('open');
	};

	this.close = function ()
	{
		transmission.hideMobileAddressbar();
		data.elements.root.dialog('close');
	},

	this.shouldAddedTorrentsStart = function()
	{
		return data.elements.root.find('#start-added-torrents')[0].checked;
	};

	data.dialog = this;
	initialize (remote);
};
