/**
 * Measure converter
 * 
 * @author slava
 */
(function($){
	$.fn.measure = function(options){
		var defaults = {
			equal: '.equal span',
			input: {
				container: '.input',
				value: 'input.value',
				valueHelper: 'span.value',
				unit: '.unit'
			},
			inputError: 'input-error',
			roundMax: 5,
			output: {
				container: '.output',
				value: 'input.value',
				valueHelper: 'span.value',
				unit: '.unit'
			},
			outputError: 'output-error',
			resultLinks: 'result-links',
			round: 2,
			selected: 'selected bg bg-h36 dc-bg',
			speed: 'light'
		}
		
		options = $.extend(defaults, options);
		
		return this.each(function(){
			var el = $(this);
			
			if (el.data('measure')) return;
			
			var measure = new Measure(this, options);			
			el.data('measure', measure);
		});
	}
	
	var Measure = function(el, options){
		var el = $(el);
		var self = this;
		this.options = options;
		
		this.converts = 0;
		
		this.input = {};
		this.output = {};
		
		this.init = function(){
			var o = options;
			
			// input
			var inputContainer = el.find(o.input.container);
			this.input.value = inputContainer.find(o.input.value);
			this.input.select = inputContainer.find(o.input.unit);
			this.input.valueHelper = inputContainer.find(o.input.valueHelper);
			
			// output
			var outputContainer = el.find(o.output.container);
			this.output.value = outputContainer.find(o.output.value);
			this.output.select = outputContainer.find(o.output.unit);
			this.output.valueHelper = outputContainer.find(o.output.valueHelper);
			
			// default value from hash
			var url = document.location.pathname.replace(/^.*measure\//, '').split('/');
			if(url[url.length - 1] == '')
				url.pop();
			
			if(url.length > 1) {
				if (url[1]) {
					this.input.select.val(url[1]);
				}
				if(url[2]) {
					this.output.select.val(url[2]);
				} else {
					if (o.converterType == 'frequency') {
						this.output.select.find('option:eq(0)')[0].selected = true;
					} else {
                        var index = this.input.select.attr('selectedIndex');
                        if(index == 0) { index++;   }
                        else           { index = 0; }
						this.output.select.find('option:eq(' + index + ')')[0].selected = true;
					}
				}
				if(url[3]) {
					this.input.value.val(url[3]);
				}
                else {
                    this.input.value.val(1);
                }
			} else {
				var hash = document.location.hash.toString().replace('#', '');
				var aHash = hash.split('_');
				if (aHash.length) {
					if (aHash[0] && aHash[0] != '') {
						this.input.value.val(aHash[0]);
						
						if (aHash[1]) {
							this.input.select.val(aHash[1]);
							
							if (aHash[2]) {
								this.output.select.val(aHash[2]);
							}
						}
					} else {
						if (o.converterType == 'frequency') {
							this.output.select.find('option:eq(0)')[0].selected = true;
						} else {
							this.output.select.find('option:eq(1)')[0].selected = true;
						}
					}
				} else {
					this.output.select.find('option:eq(1)')[0].selected = true;
				}
			}
			
			// selectmenu function
			function close(event, selectmenu) {
				var list = selectmenu.list;
				list.shadow('hide');
				$(document).trigger('hideCluetip');
				content.height('');
			}
			
			function format(text) {
				var formattedText = text.replace('|', '<span class="bubble-link" rel=".measure-converter .bubble-content"></span>');
				return formattedText;
			}
			
			function open(event, selectmenu) {
				var list = selectmenu.list;
				list.css('top', selectmenu.newelement.children().offset().top);
				if (o.converterType != 'information') {
					if(!IE6) 
						list.width('auto');
				} else {
					if (!list.find('li.empty').length) {
						var li = $('<li class="clear"></li>');						
						list.find('li').eq(1).after(li);
					}
				}
				
				list.shadow();
				list.shadow('show');
				var IE7 = $.browser.msie && $.browser.versionX == 7;
				var paddingTop = parseInt(content.css('padding-top').replace('px', ''));
				
				if(IE7) paddingTop = 0;
				var conHeight = content.height() + paddingTop + content.offset().top;
				if(IE6) conHeight -= paddingTop;
				
				if(list.height() + list.offset().top > conHeight) {
					content.height(list.height() + list.offset().top - content.offset().top - (IE6 || IE7 ? 50 : paddingTop));
				}
			}
			
			// init input section
			this.setInputWidth(this.input.value, '0');
			this.input.value.focus();
			
			// rounder
			this.input.value.rounder({
				helper: this.output.valueHelper
			});
			this.input.value.rounder('hide');
			
			// init select
			this.input.select.change(function(){
				self.convert(el.find('input.value-active'));
			});
			// init menu
			/*
			this.input.select.selectmenu({
				close: close,
				format: format,
				open: open,
				style: 'dropdown',
				transferClasses: true,
				menuWidth: o.converterType == 'information' ? '33.18em' : null
			});
			*/
			// init tips
			var inputUnit = this.input.unit = $('ul[id^='+inputContainer.find(o.input.unit)[0].id+'_menu]');
			inputUnit.find('.bubble-link').cluetip();
			
			
			// init output section
			this.setInputWidth(this.output.value);
			
			// rounder
			this.output.value.rounder({
				helper: this.output.valueHelper
			});
			this.output.value.rounder('hide');
			//
			
			// init select
			this.output.select.change(function(){
				self.convert(el.find('input.value-active'));
			});
			// bug here: horizontal scroll
			/*
			this.output.select.selectmenu({
				close: close,
				format: format,
				open: open,
				style: 'dropdown',
				transferClasses: true,
				menuWidth: o.converterType == 'information' ? '33.18em' : null
			});
			*/
			//*
			var outputUnit = this.output.unit = $('ul[id^='+outputContainer.find(o.output.unit)[0].id+'_menu]');
			outputUnit.find('.bubble-link').cluetip();
			
			// binds
			var inputs = el.find('input.value');
			// select input element
			inputs.focus(function(){
				var $this = $(this);
				inputs.removeClass('value-active');
				$this.addClass('value-active').removeClass('value-out');
				self.setInputWidth($this, '0');
				
				if($this.parent().hasClass('input')) {
					var outputClass = '.output';
				} else {
					var outputClass = '.input';
				}
				
				// select output inputs
				el.find(outputClass+' input.value').each(function() {
					var $this = $(this);
					$this.addClass('value-out');
					self.setInputWidth($this);
					
					$this.rounder('update');
				});
			});
			
			// enter value
			inputs.bind('keyup input', function(event){
				var code = event.keyCode;
				if(!self.isControlKey(event.type, code)) {
					self.convert($(this), event.keyCode);
				}
				self.setInputWidth($(this), '0');
			});
			
			// equal click
			if (o.equal) {
				var equal = el.find(o.equal);
				equal.css({
					cursor: 'pointer'
				});
				equal.click(function(){
					if (!el.find('.input-error').length) {
						var value = self.input.value.val();
						self.input.value.val(self.output.value.val());
						self.output.value.val(value);
						
						var select = self.input.select.val();
						self.input.select.val(self.output.select.val());
						self.output.select.val(select);
						
						self.convert(el.find('.value-active'));
					}
				});
			}
			//*/
			el.css('visibility', 'visible');
			this.convert(this.input.value);
		}
		
		/**
		 * set input width
		 * 
		 * @param {Object} input
		 * @param {String} add
		 */
		this.setInputWidth = function(input, add) {
			var helper = $('#expanderHelper');
			if (!helper.length) {
				helper = $('<div id="expanderHelper" style="position: absolute; top: 0; left: 0; visibility: hidden;"></div>');
				$('body').append(helper);
			}
			var text = input.val();
			if (text) {
				var style = {
					fontFamily: input.css('fontFamily')||'',
					fontSize: input.css('fontSize')||'',
					fontWeight: input.css('fontWeight')||'',
					fontStyle: input.css('fontStyle')||'',
					fontStretch: input.css('fontStretch')||'',
					fontVariant: input.css('fontVariant')||'',
					letterSpacing: input.css('letterSpacing')||'',
					wordSpacing: input.css('wordSpacing')||''
				};
				
				helper.css(style);
				
				if(add) {
					text += add;
				}
				helper.text(text);
				
				var width = helper.width();
				input.width(width);
			}
		}
		
		/**
		 * check pressing control keys
		 * 
		 * @param {Object} eventType
		 * @param {Number} code
		 */
		this.isControlKey = function(eventType, code) {
			var controlKeys = [];
			switch(eventType) {
				case 'keyup':
					controlKeys = [16, 35, 36, 37, 38, 39, 40];
					break;
				default:
					break;
			}
			
			for(var i in controlKeys) {
				if(controlKeys[i] == code) return true;
			}
			
			return false;
		}
		
		/**
		 * main interface convert function
		 * 
		 * @param {Object} input
		 * @param {Number} keyCode
		 */
		this.convert = function(input, keyCode){
			var o = options;
			var value = input.val();
			var from = input.nextAll('.unit').val();
			
			if (input.parent().hasClass('input')) {
				var output = el.find('.output input.value');
			} else {
				var output = el.find('.input input.value');
			}
			
			// check empty string
			if ($.trim(value) != '' && $.trim(value) != '-') {
				if (o.converterType == 'frequency') {
					var inputNum = measureConverter.convert(value, o.converterType, from, from, {speed: o.speed});
				} else {
					var inputNum = measureConverter.convert(value, o.converterType, from, from);
				}
				
				// if itself convertion correct
				if(inputNum !== false) {
					input.parent().removeClass(o.inputError);
					input.parent().removeClass(o.outputError);
					output.parent().removeClass(o.inputError);
					output.parent().removeClass(o.outputError);
					
					// input
					var isActive = input.hasClass('value-active');
					
					if (isActive) {
						input.rounder('hide');
											
						var spacerCount = value.match(/ /g);
					}
					
					var inputNumFormatted = this.formatNum(value);
					
					if(isActive) {
						var spacerCount2 = inputNumFormatted.match(/ /g);
						spacerCount = (spacerCount2 ? inputNumFormatted.match(/ /g).length : 0) - (spacerCount ? spacerCount.length : 0);
						
						var elem = input[0];
						var caretPos = 0;
						
						if (elem.createTextRange) {
							var r = document.selection.createRange().duplicate();
							r.moveEnd('character', elem.value.length);
							if (r.text == '') {
								caretPos = elem.value.length + spacerCount;
							} else {
								caretPos = elem.value.lastIndexOf(r.text) + spacerCount;
							}
						} else if (elem.selectionStart) {
							caretPos = elem.selectionStart + spacerCount;
						}
					}
					
					input.val(inputNumFormatted);
					this.setInputWidth(input, '0');
					
					if(isActive) {	
						if (elem.selectionStart) {
							if(value.charAt(caretPos-1) == ' ' && keyCode && keyCode == 8) {
								elem.setSelectionRange(caretPos-1, caretPos-1);
							} else {
								elem.setSelectionRange(caretPos, caretPos);
							}
						} else if (elem.createTextRange) {
							var range = elem.createTextRange();
							if(value.charAt(caretPos-1) == ' ' && keyCode && keyCode == 8) {
								range.move('character', caretPos-1);
							} else {
								range.move('character', caretPos);
							}
							range.select();
						} else {
							elem.focus();
						}
					}
					
					this.setUnitNoun(inputNum, from, input.parent().find('.ui-selectmenu-status'));
					
					// output
					var to = output.nextAll('select').val();
					
					if (o.converterType == 'frequency') {
						var outputNum = measureConverter.convert(value, o.converterType, from, to, {speed: o.speed});
					} else {
						var outputNum = measureConverter.convert(value, o.converterType, from, to);
					}
					var outputNumFormatted = this.formatNum(outputNum, 'output');
					output.val(outputNumFormatted);
					this.setInputWidth(output);
					output.rounder('update', outputNum);
					
					this.setUnitNoun(outputNum, to, output.parent().find('.ui-selectmenu-status'));
					
					var inputVal = value.replace('.', ',').replace(/\s+/g, '');
					this.setResultLinks(inputVal, from, to);
                    
                    this.displayComments(from, to);
					
					this.converts++;
				} else {
					input.parent().addClass(o.inputError);
					output.parent().addClass(o.outputError);
				}
			}
		}
		
        this.displayComments = function(from, to) {
			var measureDesc = $('#measureDescriptions');
            var descLeft = document.getElementById('descLeft');
            var descRight = document.getElementById('descRight');
            var descFrom = document.getElementById('desc-' + from);
            var descTo = document.getElementById('desc-' + to);
            
            if (!descLeft || !descRight || !descFrom || !descTo) {
				measureDesc.hide();
			} else {
				descLeft.innerHTML = descFrom.innerHTML;
            	descRight.innerHTML = from == to ? '' : descTo.innerHTML;
				measureDesc.show();
			}
        }
        
		this.formatNum = function(num, numType) {
			var o = options;
			
			var str = this.expandExponential(num);
			
			if(typeof num == 'number') {
				var arr2 = str.split('.');
				var precision = o.round;
				if(Math.abs(parseInt(arr2[0])) > 0) {
					precision += arr2[0].replace('-', '').length;
				} else {
					if(Math.abs(num.toPrecision(precision)) >=1) {
						precision++;
					}
				}
				
				str = num.toPrecision(precision).toString();
				str = this.expandExponential(str);
			}
			
			var value = str.replace('.', ',').replace(/\s+/g, '');
			var arr = value.split(',');
			if(arr[0].length > 3) {
				arr[0] = arr[0].replace(/(\d{1,3}(?=(\d{3})+$))/g,'\$1 ');
			}
			
			var value = arr.join(',');
			if (parseInt(this.expandExponential(num)) == num && numType == 'output') {
				value = arr[0];
			}
			return value;
		}
		
		this.setUnitNoun = function(num, unit, selectmenu){
			var noun = this.getNoun(num, unit);
			selectmenu.text(noun);
		}
		
		this.getNoun = function(num, unit) {
			num = Math.abs(num);
			
			if (num.toString().indexOf('.') != -1) {
				var numDecl = 1;
			} else { 
				var numDecl = (
					num % 10 == 1 && num % 100 != 11 
						? 0 
						: num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) 
							? 1 
							: 2
				);
			}
			
			return options.locale[unit][numDecl];
		}
		
		this.setResultLinks = function(num, from, to){
			var o = options;
			var url = document.location.toString().replace(/^(.*)(measure\/)(.*)$/, '$1$2') + o.converterType + '/' + from + '/' + to + '/' + num;
			var codeText = '';
			
			var resultLinks = $('#' + o.resultLinks);
			
			if (o.converterType == 'frequency') {
				codeText = s('wavelength with frequency', num, this.getNoun(num, from), o.locale[to][3]);
			} else {
				codeText = num + ' ' + this.getNoun(num, from) + ' ' + s('in') + ' ' + o.locale[to][3];
			}
			
			resultLinks.find('#result-link-url').val(url);
			resultLinks.find('#result-link-code').val('<a href="' + url + '">' + codeText + '</a>');
		}
		
		this.expandExponential = function(n){
			return n.toString().replace(/^([+-])?(\d+).?(\d*)[eE]([-+]?\d+)$/, function(x, s, n, f, c){
				var l = +c < 0, i = n.length + +c, x = (l ? n : f).length, c = ((c = Math.abs(c)) >= x ? c - x + l : 0), z = (new Array(c + 1)).join('0'), r = n + f;
				return (s || '') + (l ? r = z + r : r += z).substr(0, i += l ? z.length : 0) + (i < r.length ? '.' + r.substr(i) : '');
			});
		}
		
		this.init();
	}
})(jQuery);

var measureConverter = {
	convert: function(value, type, from, to, options){
		if (this.isNum(value, type, from) && this[type]) {
			
			var num = this.prepare(value, type);
			
			if (from == to) return num;
			
			switch(type) {
				case 'temperature':
					return this[type].from(this[type].to(num, from), to);
					break;
				
				case 'frequency':
					var isFreq = false;
					var o = options;
					for(var unit in this.frequency.coef) {
						if(from == unit) {
							isFreq = true;
							break;
						}
					}
					if(isFreq) {
						var freq = this[type].to(num, from);
						var length = this['frequency-length'].f2l(freq, o.speed);
						return this['length'].from(length, to);
					} else {
						var length = this['length'].to(num, from);
						var freq = this['frequency-length'].l2f(length, o.speed);
						return this[type].from(freq, to);
					}
					break;
					
				default:
					if(this[type].coef[from] && this[type].coef[to]) {
						return this[type].from(this[type].to(num, from), to);
					} else {
						return false;
					}
					break;
			}
			
			return value;
		} else {
			return false;
		}
	},
	
	prepare: function(value, type){
		var num = new Number(value.replace(',', '.').replace(/\s+/g, ''));
		
		return num;
	},
	
	isNum: function(value, type, unit){
		var flag = true;
		
		value = value.toString().replace(',', '.').replace(/\s+/g, '');
		/*
		if(type == 'angle' && unit == 'sec') {
			if(value.search(/^-?(\d+')?(\d+")?$/) == -1) {
				return false;
			}
		}
		*/
		if(isNaN(value)) {
			flag = false;
		} else {
			switch (type) {
				case 'temperature':
					if(this[type].from(this[type].to(Number(value), unit), 'k') < 0) {
						flag = false;
					}
					break;
					
				default:
					flag = true;
					break;
			}
		}
		
		return flag;
	},
	
	mass: {
		coef: {
            t: 1000,
			kg: 1,
			g: 0.001,
			lb:0.4535923744953,
			lbt: 0.373241718913976,
			oz: 0.028349523125,
			ozt: 0.0311034763826794,
			pood: 16.380496,
			ct: 0.0002,
            gr: 0.0006479891
		},
		
		to: function(mass, unit) {
			return mass * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	length: {
		coef: {
			m: 1,
			km: 1000,
			cm: .01,
			mm: .001,
			yd: .9144,
			ft: .3048,
			'in': .0254,
			mi: 1609.344,
			nmi: 1852,
			arshin: .7112,
			a: .0000000001,
            ell: 0.55,
            verst: 1066.781,
            sazhen: 2.1336,
            vershok: 0.04445,
            unit:    0.04445,
            span: 0.1778,
            league: 4445
		},
		
		to: function(length, unit) {
			return length * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	area: {
		coef: {
			m2: 1,
			cm2: .0001,
			mm2: .000001,
			km2: 1000000,
			ft2: .09290304,
			in2: .000645156494804761,
			acre: 4046.86,
			'irish-acre': 6553.851239669421487603305785124,
			'scots-acre': 5000,
			ha: 10000,
			are: 100,
            stk: 100,
			mi2: 2589988.110336,
			dunam: 1000,
			yd2: .83612736,
			rai: 1600,
			ca: 1
		},
		
		to: function(area, unit) {
			return area * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	volume: {
		coef: {
			m3: 1,
            km3: 1000000000,
			cm3: .000001,
			mm3: .000000001,
			dal: .01,
			l: .001,
			ml: .000001,
			gal: .003785411784,
			qt: .000946352946,
			pt: .000473176473,
			barrel: .158987294928,
			ozfl: .0000295735295625,
			yd3: .764554857984,
			ft3: .028316846592,
			in3: .000016387064,
			gald: .00440488377086,
			qtd: .001101220942715,
			ptd: .0005506104713575,
			barreld: .115628198985075,
			bu: .07047814033376,
			gali: .00454609,
			qti: .0011365225,
			pti: .00056826125,
			barreli: .16365924,
			ozfli: .0000284130625,
			bui: .03636872,
			barrelu: .1192,
			barrele: .16365,
			barrelb: .16366,
            mdrop: .000000050,
            medrop: .000000083,
            dash: .00000002,
            tsp: .00000493,
            tbsp: .000014790
		},
		
		to: function(volume, unit) {
			return volume * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	speed: {
		coef: {
			kmh: 1,
			mps: 3.6,
			mph: 1.609344,
			nmih: 1.852,
			kn: 1.852,
			fps: 1.09728
		},
		
		to: function(area, unit) {
			return area * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	pressure: {
		coef: {
			bar: 1,
			pa: .00001,
			torr: .00133322,
			mmhg: .00133322,
			atm: 1.01325,
			at: .980665,
			psi: .06894757,
			inhg: .033863788,
			dyncm2: .000001,
            kgfm2: 0.000098066
		},
		
		to: function(pressure, unit) {
			return pressure * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	force: {
		coef: {
			n: 1,
			dyn: .00001,
			kgf: 9.80665,
			lbf: 4.4482216152605,
			kip: 4448.2216152605,
			gf: .00980665
		},
		
		to: function(force, unit) {
			return force * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	energy: {
		coef: {
			j: 1,
			erg: .0000001,
			kwh: 3600000,
			ev: .000000000000000000160217653141414,
			cal: 4.1868,
			kgtnt: 4612000000,
			btu: 1055.05585257348,
			kgfm: 9.80665,
			ftlbf: 1.3558179483314004
		},
		
		to: function(energy, unit) {
			return energy * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	power: {
		coef: {
			w: 1,
			kw: 1000,
			ergs: .0000001,
			ls: 735.49875,
			hp: 745.69987158227022,
			kcalh: 1.163,
			cals: 4.1868,
			btus: 1055.05585257348,
			kgfms: 9.80665
		},
		
		to: function(power, unit) {
			return power * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	information: {
		coef: {
			bit: 1,
            nibble: 4,
			b: 8,
			
			kbit: 1000,
			kb: 8192,
			kib: 8000,
			
			mbit: 1000000,
			mb: 8388608,
			mib: 8000000,
			
			gbit: 1000000000,
			gib: 8589934592,
			gb: 8000000000,
			
			tbit: 1000000000000,
			tib: 8796093022208,
			tb: 8000000000000,
			
			pbit: 1000000000000000,
			pib: 9007199254740992,
			pb: 8000000000000000,
			
			ebit: 1000000000000000000,
			eib: 9223372036854775808,
			eb: 8000000000000000000,
			
			zbit: 1000000000000000000000,
			zib: 9444732965739290427392,
			zb: 8000000000000000000000,
			
			ybit: 1000000000000000000000000,
			yib: 9671406556917033397649408,
			yb: 8000000000000000000000000
		},
		
		to: function(information, unit) {
			return information * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	oil: {
		coef: {
			bbloil: 1,
			tonn: 7.33,
			mmkl: 6.2898107704321
		},
		
		to: function(oil, unit) {
			return oil * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	gas: {
		coef: {
			m3gas: 1,
			ft3gas: .0283205890682526,
			tonnspg: 1400,
			lgas: .001,
			galusa: .00378501135503407,
			galuk: .00454545454545455
		},
		
		to: function(gas, unit) {
			return gas * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}		
	},
	
	temperature: {
		to: function(temperature, unit) {
			var def = temperature;
			switch(unit) {
				case 'k':
					break;
				case 'c':
					def = def + 273.15;
					break;
				case 'f':
					def = (def + 459.67) * (5 / 9);
					break;
				case 'r':
                    def = def * (5 / 9);
					break;
				case 'de':
                    def = 373.15 - def * (2 / 3);
					break;
				case 'ne':
                    def = def * (100 / 33) + 273.15;
					break;
				case 're':
                    def = def * (5 / 4) + 273.15;
					break;
				case 'ro':
                    def = (def - 7.5) * (40 / 21) + 273.15;
					break;
					
			}
			return def;
		},
		
		from: function(def, unit){
			var temperature = def;
			switch(unit) {
				case 'k':
					break;
				case 'c':
					temperature = temperature - 273.15;
					break;
				case 'f':
					temperature = (temperature * (9 / 5)) - 459.67;
					break;
				case 'r':
                    temperature = temperature * (9 / 5);
					break;
				case 'de':
                    temperature = (373.15 - temperature) * (3 / 2);
					break;
				case 'ne':
                    temperature = (temperature - 273.15) * (33 / 100);
					break;
				case 're':
                    temperature = (temperature - 273.15) * (4 / 5);
					break;
				case 'ro':
                    temperature = (temperature - 273.15) * (21 / 40) + 7.5;
					break;
			}
			return temperature;
		}
	},
	
	time: {
		coef: {
			ns: .000000001,
			us: .000001,
			ms: .001,
			second: 1,
			minute: 60,
			hour: 3600,
			day: 86400,
			week: 604800,
			year: 31536000,
			century: 3153600000,
			th: 31536000000
		},
		
		to: function(time, unit) {
			return time * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}
	},
	
	angle: {
		coef: {
			rad: 1,
			degree: Math.PI/180,
			min: Math.PI/180/60,
			sec: Math.PI/180/3600,
			turn: 2*Math.PI,
			grad: Math.PI/200,
			mil: .001047
		},
		
		to: function(angle, unit) {
			return angle * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}
	},
	
	frequency: {
		coef: {
			microHz: .000001,
			mHz: .001,
			Hz: 1,
			kHz: 1000,
			MHz: 1000000,
			GHz: 1000000000,
			THz: 1000000000000
		},
				
		to: function(freq, unit) {
			return freq * this.coef[unit];
		},
		
		from: function(def, unit){
			return def / this.coef[unit];
		}
	},
	
	'frequency-length': {
		speed: {
			light: 299792458,
			sound: 331.46
		},
		
		f2l: function(freq, speed) {
			if(typeof speed == 'undefined') {
				speed = this.speed.light;
			} else if(typeof speed == 'string'){
				speed = this.speed[speed];
			}
			
			return speed / freq;
		},
		
		l2f: function(length, speed) {
			if(typeof speed == 'undefined') {
				speed = this.speed.light;
			} else if(typeof speed == 'string'){
				speed = this.speed[speed];
			}
			
			return speed / length;
		}
	}
}
