/**
 * @author Jae Cho
 * set of utility functions
 */

// to avoid double posting to Facebook when rating / reviewing game simulataneously
var facebookPostReviewOnly = false;

/**
 * context bind method
 * in JS, the keyword 'this' means the current closure instead of the
 * object in which the method is defined. This causes problems in callback
 * methods. Use this bind method to bind object to the method
 * got it from http://fn-js.info/snippets/bind
 * @param obj
 * @param fun
 * @param args
 */
function bindContext(obj, fun, args) {
  return function() {
    if (obj === true)
      obj = this;
    var f = typeof fun === "string" ? obj[fun] : fun;
    if (f) {
        return f.apply(obj, Array.prototype.slice.call(args || [])
                .concat(Array.prototype.slice.call(arguments)));
    }
    else
    {
    	alert(obj + ", " + fun + "," + args);
    }
  };
}

function postFlag(itemId, itemType, itemDesc) {
	var report = new com.ag.ReportUserSubmittedContentAbuse();
	report.init({'itemId':itemId,'typeCode':itemType,'typeDesc':itemDesc});
}




/**
* CookieUtil
* utility class for handling cookies
* copied from dojo.cookie
*/
function CookieUtil (){
  this.cookie = function(name,value,props){
	var c = document.cookie;
	if(arguments.length == 1){
		var idx = c.lastIndexOf(name+'=');
		if(idx == -1){ return null; }
		var start = idx+name.length+1;
		var end = c.indexOf(';', idx+name.length+1);
		if(end == -1){ end = c.length; }
		return decodeURIComponent(c.substring(start, end));
	}else{
		props = props || {};
		value = encodeURIComponent(value);
		if(typeof(props.expires) == "number"){
			var d = new Date();
			d.setTime(d.getTime()+(props.expires*24*60*60*1000));
			props.expires = d;
		}
		document.cookie = name + "=" + value
			+ (props.expires ? "; expires=" + props.expires.toUTCString() : "")
			+ (props.path ? "; path=" + props.path : "")
			+ (props.domain ? "; domain=" + props.domain : "")
			+ (props.secure ? "; secure" : "");
		return null;
    }
  };
     /**
     * set AG Status cookie
     * @param key
     * @param value
     */
    this.setAgStatus = function(key,value){
      var status = this.cookie("widgetStatus");
      if (status) {
        var _agStatus = JSON.parse(status,function(key,value){
            return value;
        });
        if(!_agStatus){_agStatus = new Object();}
        _agStatus[key] = value;
        this.cookie("widgetStatus",JSON.stringify(_agStatus), {"expires":1});
      }
    };

    /**
     * get AG Status value for key
     * @param key
     */
    this.getAgStatus = function(key){

      var status = this.cookie("widgetStatus");
      if (status) {
        var _agStatus =  JSON.parse(status,function(key,value){
            return value;
        });
        if(_agStatus) return _agStatus[key];
        }
            return null;

    };

    /**
     * erase cookie
     * @param name
     */
    this.eraseCookie = function(name) {
        this.createCookie(name,"",-1);
    };
}


/**
 * StringUtil
 */
function StringUtil() { }

/** delimiters used to input multiple email addess */
StringUtil.EMAIL_DELIMITER_PATTERN = /[\,\;\r\n\f\v:]+/;

/** pattern for email */
StringUtil.EMAIL_PATTERN = /^(?:[\w\.])+@(?:[\w]+)(?:\.(?:[\w])+)+/;

/** pattern for name jae <jaecho@yo.com> */
StringUtil.NAME_PATTERN1 = /<([\S+]+)>\s*([\w ]+)/;
StringUtil.NAME_PATTERN2 = /([\w ]+)\s*<([\S+]+)>/;


/** returns true if str is a valid email */
StringUtil.isValidEmail = function(str) {
    return str.match(this.EMAIL_PATTERN);
};

StringUtil.trim = function (stringToTrim) {
    return stringToTrim.replace(/^\s+|\s+$/g,"");
};


/** @return array of email objects for each entry
* status - valid, invalid
* email - parsed email address
* name - name if < > is provided
*/
StringUtil.parseEmails = function(emails) {
    var entries = emails.split(this.EMAIL_DELIMITER_PATTERN);
    var parsedEntries = new Array();

    for (var i = 0; i < entries.length; i++) {

        var string = entries[i];
        if (!string) continue;

        string = this.trim(string);

        var parsedEntry  = this.parseEntry(string);
        parsedEntries.push(parsedEntry);

        if (this.EMAIL_PATTERN.test(parsedEntry.email)) {
            parsedEntry.status = "valid";
        } else {
            parsedEntry.status = "invalid";
        }
    }
    return parsedEntries;
};

/**
 * parse an entry in email list string into name and email address.
 * @param string
 */
StringUtil.parseEntry = function(string) {
    var res;
    var parsedEntry = new Object();
    parsedEntry.string = string;

    res = string.match(this.NAME_PATTERN1);
    if (res) {
        parsedEntry.name = res[2];
        parsedEntry.email = res[1];
        return parsedEntry;
    }

    res = string.match(this.NAME_PATTERN2);
    if (res) {
        parsedEntry.email = res[2];
        parsedEntry.name = res[1];
        return parsedEntry;
    }

    parsedEntry.email = string;
    return parsedEntry;
};



/** return a map containing request query parameters and values in string
 * for example, request with http://yo.com?v0=1&v1=2 will return
 * { "v0" : "1", "v1" : "2" }
 * @param queryStr value of window.location.search variable
 */
StringUtil.getQueryParams = function(queryStr) {

    var query = queryStr.substring(1);
    var vars = query.split("&");
    for (var i=0;i<vars.length;i++) {
        var pair = vars[i].split("=");
        vars[pair[0]] = pair[1];
    }
    return vars;
};

/** return a string chopped up into n characters, separated by spaces.
 * This is used to force a wrap on extra long words, to prevent display issues
 *
 * @param str = string to be chopped
 * @param charMax = number of characters per segment
 */
StringUtil.wordChopper = function(str, charMax){
    if (!str) return str;

    var strArr = str.split(" ");
    for (i=0;i<strArr.length;i++){
       var charCount = strArr[i].length;
       if (charCount < charMax){
           //don't modify the string
           continue;
       }
      var segCount = charCount / charMax;
      var newStr = "";
      for (j=0; j<=segCount;j++){
          newStr += strArr[i].substr(j*charMax,charMax) + " ";
      }
      strArr[i] = newStr;
    }
  return strArr.join(" ");
}
/**
 * DateUtil
 */
function DateUtil() { }

DateUtil.SECOND_MS = 1000;
DateUtil.MIN_MS = DateUtil.SECOND_MS * 60;
DateUtil.HOUR_MS = DateUtil.MIN_MS * 60;
DateUtil.DAY_MS = DateUtil.HOUR_MS * 24;


DateUtil.calculateAge = function(time1, time2) {
    var diff = time1 - time2;
    return DateUtil.formatAge(diff);
};

DateUtil.formatAge = function(ageInMs) {

    var diffInUnit;
    var unit;

    if (ageInMs <= DateUtil.MIN_MS) {
        diffInUnit = Math.round(ageInMs / DateUtil.SECOND_MS);
        unit = diffInUnit == 1 ? "second" : "seconds";
    } else if (ageInMs <= DateUtil.HOUR_MS) {
        diffInUnit = Math.round(ageInMs / DateUtil.MIN_MS);
        unit = diffInUnit == 1 ? "minute" : "minutes";
    } else if (ageInMs <= DateUtil.DAY_MS) {
        diffInUnit = Math.round(ageInMs / DateUtil.HOUR_MS);
        unit = diffInUnit == 1 ? "hour" : "hours";
    } else {
        diffInUnit = Math.round(ageInMs / DateUtil.DAY_MS);
        unit = diffInUnit == 1 ? "day" : "days";
    }

    return diffInUnit + " " + unit;
};

DateUtil.dojoDifference = function(date1, date2, period) {
    return dojo.date.difference(date1, date2, period);
};


function NumberUtil() {};

NumberUtil.addCommas = function(nStr)
{
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
};



function ProfileUtil() {};

/**
 * get profile image path
 * @param args - map of various argments
 * - userId or userUuid - one of them is required
 * - size (optional) - "large" or "small (default)"
 * If true, server will show image in moderation queue if present.
 * If true, append date string so that browser does not cache the image
 */
ProfileUtil.getImg = function(args) {
    var path = "/dynamic/photo/userPic?";
    var defaultPath = "/static/images/user_pic_default_";
    var self = false;
    var cutil = new CookieUtil();
    var facebookId = LoginModule.getSessionFacebookId();
    if (!facebookId) {
		if (!args.userPicSet && typeof args.userPicSet != "undefined"){
			if (args.size)return defaultPath + args.size + ".jpg";
			else return defaultPath + "small.jpg";
		}
    }
    if (args.userId) {
        path += "userId=" + args.userId;
        if (cutil.cookie("aguseridsc") == args.userId) self = true;

    } else if (args.userUuid) {
        path += "userUuid=" + args.userUuid;
        if (cutil.cookie("aguseruuidsc") == args.userUuid) self = true;

    } else {
        return null;
    }

    if (args.size == "big") path += "&thumbnail=false";
    else path += "&thumbnail=true";

    if (self) {
        path += "&self=true";
        path += "&date=" + (new Date()).getTime();
    }
    return path;
};

/* Plugin to clear form data
   Usage: $('form').clearForm()  or $('#registration_form').clearForm()
 */
$.fn.clearForm = function() {
 return this.each(function() {
   var type = this.type, tag = this.tagName.toLowerCase();
   if (tag == 'form')
     return $(':input',this).clearForm();
   if (type == 'text' || type == 'password' || tag == 'textarea')
     this.value = '';
   else if (type == 'checkbox' || type == 'radio')
     this.checked = false;
   else if (tag == 'select')
     this.selectedIndex = 0;
 });
};


// Event classes are used for inter-module communication
// There are three main methods - subscribe, publish, unsubscribe
function AgEvent() {
	this.subscribers = [];

	// publish the event to all subscribers
	this.publish = function(data) {

		// hack to make sure all subscribers are published too, even if some are removed during the publish execution
		// just copy to another list while executing on
		var currentSubscribers = this.subscribers;

		for (var index in currentSubscribers){
			currentSubscribers[index](data);
		}
	};
	// subscribe a callback method to an event
	this.subscribe = function(callback) {
		this.subscribers.push(callback);
		return callback;
	};

	// unsubscribe a callback method from an event
	this.unsubscribe = function(callback) {
		var subscribersNew =[];
		for (var index in this.subscribers){

			// hack to serialize a function into a string for comparison to the other subscribed functions
			// NOTE: this may fail if the serialized function has closure values that are different!
			if (callback.toString() != this.subscribers[index].toString()) {
				subscribersNew.push(this.subscribers[index]);
			}
		}
		this.subscribers = subscribersNew;
	};

    // subscribe to the event only once
    this.subscribeOnce = function(callback) {
        var wrapper = new AgEventWrapper();
        wrapper._event = this;
        wrapper._callback = callback;
        wrapper._subscribingCallback = bindContext(wrapper, wrapper.call);
        this.subscribers.push(wrapper._subscribingCallback);
    };
};


/** used to implement subscribeOnce */
function AgEventWrapper() {
    this._event = null;
    this._callback = null;
    this._subscribingCallback = null;
    
    this.call = function(data) {
        this._callback(data);
        this._event.unsubscribe(this._subscribingCallback);
    };
};

// Events
AgEvent.LOGIN = new AgEvent();
AgEvent.CANCEL_LOGIN = new AgEvent();
AgEvent.REGISTER = new AgEvent();
AgEvent.CANCEL_REGISTER = new AgEvent();
AgEvent.LOGOUT = new AgEvent();

$(document).ready(function(){

	var warningLink = '<a href="/help/content-ratings.jsp" id="warningLinkFromNick"></a>';
	var categoryWarningLink = '<a href="/help/content-ratings.jsp" id="categoryWarningLink"></a>';

	function showWarningLink() {

		if ( mtvn.btg.config.AdSettings.DoubleClick["sections"] === "_hp" ) {
			$("#potw").before( warningLink );
		} else if (mtvn.btg.config.AdSettings.DoubleClick["sections"].indexOf("_mn") !== -1) {
			$("#potw").before( categoryWarningLink );
		}
	}

	// show the 'bumper' & warning link if the user is coming from nick.com
	if ( document.referrer != "" && document.referrer.indexOf(".nick.com") !== -1 ) {
		if ( document.referrer.indexOf("bumperFrameset") == -1 ) { // linked directly from nick.com; without a bumper
			var bumperDiv = '<div id="nickBumper" style="background: #FFF; height: 179px; padding-bottom: 5px; text-align: center;"><img src="/a/img/bumper_generic_new_d2.jpg" style="margin: 0 auto 0 auto;" width="900" height="179" /></div>';
			$("#mamabar").before( bumperDiv );

			showWarningLink();

			mtvn.btg.util.Cookie.set( 'fromNick', true, { path: '/', domain: '.addictinggames.com' } ); // write cookie value

			setTimeout( function() { $("#nickBumper").animate( {height: 0}, function() { $("#nickBumper").remove(); } ); }, 5000 );
		}
	// if the user has come from nick this session, show a 'warning' link in the right hand column
	} else if ( mtvn.btg.util.Cookie.read( 'fromNick' )  !== null ) {
		showWarningLink();
	}

});

function brandMamabarMoreOver(el) { el.className = "brand-mamabar-more-link brand-mamabar-more-link-hover"; }
function brandMamabarMoreOut(el) { el.className = "brand-mamabar-more-link"; }

// Changes yyyy-mm-dd to mm/dd/yy
function formatJSONDate(oldDate) {
	var year = oldDate.slice(2,4);
	var month = oldDate.slice(5,7);
	var day = oldDate.slice(8,10);
	var newDate = month + '/' + day + '/' + year;
	return newDate;
}
/**
 * Formats a number with commas ( 99999 -> 99,999 )
 * @param number
 */
function formatNumber( number ) {
	if ( isNaN(number) ) return number;
	if ( typeof number != "string" ) {
		number = number.toString();
	}
	for (var i = number.length-2; i>0; i-=3 ) {
		if ( i-1 > 0 ) {
			number = number.substring( 0, i-1 ) + "," + number.substring( i-1 );
		}
	}
	return number;
};
com.ag.util = {
	shortenString: function(name,maxLength) {
		if(name.match(/W/g) != null){
			maxLength =((name.match(/W/g).length)*(.818) + (maxLength - name.match(/W/g).length));
		}
		if (name.length > maxLength ) {
			name = name.substr(0, maxLength) + "...";
		}
		return name;
	}
};

// callback for agbucks json request
awardResponseCallback = function( data ) {
	var tmp = JSON.parse( data );
	userInfoModule.bucksBalance = formatNumber( tmp.MemberAwards["addictinggames-bucks"].Value );
	$.cookie('bucks_balance',userInfoModule.bucksBalance, { path: '/', domain: '.addictinggames.com' }); // write cookie value
	$("#bucksBalance").text( userInfoModule.bucksBalance ); // write ui
};

com.ag.updateBucksBalance = function() {
	var host = null;
	if ( location.host === "www.addictinggames.com" || location.host === "origin.www.addictinggames.com" ) {
		host = "http://eventmanager.addictinggames.com";
	} else {
		host = "http://dev.eventmanager.addictinggames.com";
	}

	var stub1 = userInfoModule.uuid.substring( 0, 3 );
	var stub2 = userInfoModule.uuid.substring( 3, 6 );
	var requestUrl =  host + "/addictinggames/member/" + stub1 + "/" + stub2 + "/awards." + userInfoModule.uuid + ".dat?callback=?";

	$("#bucksBalance").text ( $.cookie( 'bucks_balance' )  === null ? 0 : $.cookie( 'bucks_balance' ) ); // populate the AG Bucks balance with cookie data, otherwise '0'
	$.getJSON( requestUrl ); // get latest AG Bucks balance; automatically calls awardResponseCallback() to handle the returned data. due to jQuery quirk, fails undetectably
};

com.ag.showMoreLink = function (rawText, maxLength) {
	if(rawText.length < maxLength){
		return rawText;
	}
	var shortText = rawText.substr(0, maxLength);
	var longText = rawText.substr(maxLength, rawText.length);
	var newText = shortText +
			'<span class="showMoreLink">... <a href="#" class="showMoreText">more &gt;&gt;</a></span>' +
			'<span class="moreText" style="display:none">' + longText +
			' <a href="#" class="hideMoreText">close</a></span>';
	$('.hideMoreText').live('click',function(){
		$(this).parent().prev().show();
		$(this).parent().hide();
		return false;
	});
	$('.showMoreText').live('click', function(){
		$(this).parent().next().show();
		$(this).parent().hide();
		return false;
	});
	return newText;
};
com.ag.loginAndDo = function (doThis) {
		if(!LoginModule.isUserLoggedIn()){
			LoginModule.showLogin();
			AgEvent.LOGIN.subscribeOnce(doThis);
			AgEvent.LOGOUT.subscribeOnce(doThis);
		}else{
			doThis();
		}
	};
com.ag.recaptcha = {
	submitRecaptcha: false,
	recaptchaElement: '',
	init: function () {
		com.ag.recaptcha.submitRecaptcha = true;
		$.getScript("http://api.recaptcha.net/js/recaptcha_ajax.js",
				function() {
					Recaptcha.create(
							"6Lc_SAcAAAAAAGx9bjOU-srubELeT3EyyHR5S9sp",
							com.ag.recaptcha.recaptchaElement, {
								theme : "red",
								callback : function() {
									Recaptcha.focus_response_field();
								}
							});
				});
		}
	};
