/**
 * $.MobiVyew will render your existing site into mobile friendly pages. More information is available
 * online at http://cognitived.com/mobivyew/
 *
 * @package    MobiVyew
 * @author     Alan Roemen <alan@44interactive.com>
 * @version    0.2
 * @copyright  (c) 2011 44 Interactive
 */
(function($){

	$.MobiVyew = {
		initialize: function(options) {
			// do not run if they are not in a mobile browser
			if ( !mbv._detect_mobile() ) return this;
			mbv.time = new Date().getTime();

			// define default options and merge in passed in options
			var defaults = {
				path: '/js/mobivyew',
				vyews: '/vyews/',
				backToMobile: '#mobivyew-show',
				cookieName: 'mobivyew',
				cookiePath: '/',
				debug: false
			};
			mbv.options = $.extend(defaults, options);

			// define internal variables
			mbv.mobile = true;
			mbv.loading = null;
			mbv.options.dom = $(document);
			mbv.options.domready = false;
			mbv.options.page = location.pathname
				.replace(/\//g, '-')      // convert all slashes to dashes
				.replace(/\-+/, '-')      // convert multiple dashes into one
				.replace(/^\-|\-$/g, '')  // remove dash from beginning and end
				.replace(/^$/, 'index')   // set empty to index page
			mbv.options.append = null;

			// stop if user requested full site
			if ( mbv._cookie() ) {
				mbv.options.dom.ready(function(){
					$(mbv.options.backToMobile).click(function(){
						mbv._cookie(null);
						location.reload(true);
						return false;
					});
				});
				return this;
			}

			// start the magic!
			$.ajax({
				url: mbv.options.vyews + mbv.options.page + '.php',
				async: false,
				dataType: 'json',
				success: mbv._render,
				error: mbv._abort
			});
			mbv.options.dom.ready(mbv._clean);

			return this; // returns jQuery object
		},

		/**
		 * Detect if user agent is a mobile browser. Borrowed logic from (http://detectmobilebrowser.com/)
		 * @author  Alan Roemen <alan@44interactive.com>
		 * @since   0.2
		 **/
		_detect_mobile: function(){
			var agent = (navigator.userAgent||navigator.vendor||window.opera);
			var mobile = /android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i
				.test(agent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i
				.test(agent.substr(0,4));
			return mobile;
		},

		/*
		 * Cleans and builds a default DOM.
		 * @author  Alan Roemen <alan@44interactive.com>
		 * @since   0.2
		 * @todo    find a better way to clear the dom
		 */
		_clean: function(){
			if ( !mbv.mobile ) return;
			mbv.options.fulldom = $('html').clone();
			mbv.options.dom.find('head').empty();
			mbv.options.dom.find('body').empty();
			mbv.options.dom.find('head').append( mbv.options.fulldom.find('title') );
			mbv.options.domready = true;
		},

		/**
		 * Builds mobile DOM
		 * @author  Alan Roemen <alan@44interactive.com>
		 * @since   0.2
		 * @todo    Fix mbv.options.append variable issue
		 */
		_render: function(obj){
			if (!mbv.options.domready) {
				setTimeout(function(){ mbv._render(obj) });
				return;
			}

			// setup mobile head
			$('head').append( $('<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no" />') );
			$('head').append( $('<meta name="HandheldFriendly" content="True"/>') );

			// add heading tags and CSS
			mbv.options.append = 'head';
			$.each( obj.head, mbv._parse_data );
			if ( obj.css != '' ) $('head').append( $('<style type="text/css">' + obj.css + '</style>') );

			// add body tags
			mbv.options.append = 'body';
			$.each( obj.body, mbv._parse_data );

			// add option to force full site
			$('.tofull').click(function(){
				mbv._cookie(true);
				location.reload(true);
				return false;
			});

			// remove full DOM from memory
			delete mbv.options.fulldom;

			// load vyews.js
			$('head').append('<script type="text/javascript" src="' + mbv.options.path + 'vyews.js"></script>');

			// compile stats
			mbv.time = ((new Date().getTime() - mbv.time) / 1000).toFixed(3);
			mbv.log('Finished Loading Mobile DOM in ' + mbv.time + ' Seconds');
		},

		/**
		 * Adds content to the mobile DOM. Will fetch data from the
		 * full DOM as needed.
		 * @author  Alan Roemen <alan@44interactive.com>
		 * @since   0.2
		 */
		_parse_data: function(id, data){
			if (data.length > 1) {
				id = data[0];
				data = data[1];
			} else data = data[0];

			var action = data.match(/^\{(.+)\}$/);
			if (action) {
				switch (action[1]) {
					case 'fetch':
						var el = mbv.options.fulldom.find(id);
						if (el) data = $(el).clone();
						break;
					default:
						data = '<' + action[1];
						action = id.match(/(.+)\send$/);
						if (action) {
							var ex = new RegExp('\\s' + action[1], 'g');
							mbv.options.append = mbv.options.append.replace(ex, '');
							return;
						} else {
							var newAppend = mbv.options.append + ' ' + id;
							if (id.match(/^#/)) data += ' id="' + id.replace(/^#/, '') + '"';
							if (id.match(/^\./)) data += ' class="' + id.replace(/^\./, '') + '"';
						}
						data += '>';
						data = $(data);
						break;
				}
			}
			$( $(mbv.options.append) ).append(data);
			if (newAppend) mbv.options.append = newAppend;
		},

		/**
		 * Aborts loading the mobile DOM.
		 * @author  Alan Roemen <aroemen@cogntived.com
		 * @since   0.2
		 */
		_abort: function(){
			mbv.mobile = false;
		},

		_cookie: function(value){
			// set cookie
			if (arguments.length > 0 && String(value) !== "[object Object]") {
				var expires;

				if (value === null || value === undefined) {  // remove cookie
					expires = new Date();
					expires.setDate(expires.getDate() - 1);
				}

				value = String(value);  // cast to string
				return (document.cookie = [
						encodeURIComponent(mbv.options.cookieName), '=',
						encodeURIComponent(value),
						expires ? '; expires=' + expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
						'; path=' + mbv.options.cookiePath,
					].join(''));
			}

			// fetch cookie
			var result = new RegExp('(?:^|; )' + encodeURIComponent(mbv.options.cookieName) + '=([^;]*)').exec(document.cookie);
			return result ? decodeURIComponent(result[1]) : null;
		},

		/**
		 * Exists for debugging in browsers.
		 * @author  Alan Roemen <alan@44interactive.com>
		 * @since   0.2
		 */
		log: function(){
			if(mbv.options && mbv.options.debug && arguments.length > 0) {
				if (window.opera) {	// for opera
					opera.postError.apply(opera, arguments);
					return true;
				} else if (window.console && console.log) {	// standard for firebug and webkit browsers
					console.log.apply(console,arguments);
					return true;
				}

				// catch all; join for graceful degregation and output to alert box
				var args = (arguments.length > 1) ? Array.prototype.join.call(arguments, '') : arguments[0];
				alert(args);
				return false;
			}
			return false;
		}
	};

	var mbv = $.MobiVyew;
	$.fn.MobiVyew = $.MobiVyew.initialize;

})(jQuery);

