// Copyright SohoOS 2011. All Rights Reserved.

/**
 * @author ilya.trunov@sohoos.com  (Ilya Trunov) 
 * @fileoverview Javascript utils for SohoOS:
 *  1. Event tracking
 *  2. UI modules (tooltip)
 */

// Google Analytics init
 var _gaq = _gaq || [];
 _gaq.push(['_setAccount', 'UA-10836654-2']);
 _gaq.push(['_setDomainName', '.sohoos.com']);
 _gaq.push(['_trackPageview']);

// Totango init
var totangoTracker = null;


$(document).ready(function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  
  // Load totango script
  loadScript('http://s3.amazonaws.com/totango-cdn/sdr.js', ManageKitUtils.performEventsFromQueue);
});

function loadScript(url, callback){
  var script = document.createElement('script')
  script.type = 'text/javascript';

  if (script.readyState){  //IE
      script.onreadystatechange = function(){
          if (script.readyState == 'loaded' ||
                  script.readyState == 'complete') {
              script.onreadystatechange = null;
              callback();
          }
      };
  } else {  //Others
      script.onload = function(){
          callback();
      };
  }

  script.src = url;
  document.getElementsByTagName('head')[0].appendChild(script);
}

var ManageKitUtils = {
  ACTION_OK: "OK",
  SOHOOS_BI_URL: "/crm/managekit/bi/trackevent",
  TIMEOUT_LIMIT_MS: 5000,
  DELAY_EVENT_MS: 400,
  DEFAULT_SHORTNAME: 'SohoOS_WebSite',
  DEFAULT_USERNAME: 'WebSiteUser',
  
  eventsQueue: [],
  
  /**
   * If Totango code not loaded yet - add event to a queue
   */
  addEventToQueue: function(category, action, isEvent) {   
    var event = {category: category, action: action, isEvent: isEvent};
    this.eventsQueue.push(event);  
  },
  
  /**
   * After Totango code is loaded - call the events from the queue
   */
  performEventsFromQueue: function(){
    var currEvnet;
    
    totangoTracker = new __sdr("SP-1120-01");
    totangoTracker.identify(ManageKitUtils.DEFAULT_SHORTNAME, ManageKitUtils.DEFAULT_USERNAME);
    
    if (ManageKitUtils.eventsQueue.length > 0) {
      if (!totangoTracker.getOrg() || !totangoTracker.getUser()) {           
        totangoTracker.identify(ManageKitUtils.DEFAULT_SHORTNAME, ManageKitUtils.DEFAULT_USERNAME);   
      } 
    }
    
    while(ManageKitUtils.eventsQueue.length > 0) {
      currEvent = ManageKitUtils.eventsQueue.pop();
      if (currEvent['isEvent']) {        
        ManageKitUtils.trackTotango(currEvent['category'], currEvent['action']);
      } else {
        totangoTracker.identify(currEvent['category'], currEvent['action']);   
      }
    }
  },

  isTrackGoogle: function() {
    return true;
  },
  
  isTrackTotango: function() {
    return true;
  },
  
  isTrackSohoOS: function() {
    return true;
  },
  
  userData : {
    shortname: this.DEFAULT_SHORTNAME,
    vtiger_account_id: '',
    username: this.DEFAULT_USERNAME,
    user_id :''
  },
  
	/**
	 * Check if the system is on developemnt server.
	 * @retutn {boolean} True for development server, False for production/staging
	 */
	isDev: function() {
		return window.location.hostname.match('managekit.net');
	},
	
	/**
	 * Check if the system on production server
	 * @return {boolean} True if production server, False for dev/staging
	 */
	isProd: function() {
	  return window.location.hostname.match('sohoos.com');
	},
	
	/**
   * Check if the system on staging server
   * @return {boolean} True if staging server, False for dev/propd
   */
	isStaging: function() {
	  return window.location.hostname.match('sohobit.com') || window.location.hostname.match('sohooslab.com');
	},
	
	isOutputLog: function() {
		return this.isStaging() || this.isDev();
	  //return false;
	},
	
	/**
	 * Display a log message in browser console window.
	 * @param {?string} text Message text.
	 */
	log: function(text) {
		try {
			if (console) {
				console.log(text);
			}
		} catch (err) {
		}
	},
	
	/**
	 * Tracking a user generated event to various event tracking systmes.
	 * Google Analytics documentation: http://code.google.com/intl/en/apis/analytics/docs/tracking/eventTrackerGuide.html
	 * Totango documentation: http://dev.totango.com
	 * 
	 * @param {!string} category Event top-level module. 
	 * @param {!string} action Event action.
	 * @param {?string} opt_label Event description.
	 * @param {?number} opt_value Event additional numeric value.
   * @param {?function} opt_callback Callback function, returns success/failed data.
	 */
	trackEvent: function(category, action, opt_label, opt_value, opt_callback, opt_event_code) {
	  this.trackGoogle(category, action, opt_label, opt_value);
			
	  this.trackTotango(category, action);
			
	  this.trackSohoOS(opt_event_code, opt_value, opt_callback);
	},
	
	/**
	 * Track an event just by code (no module + action)
	 * 
	 * @param {!string} event_code Code of the event, see full list in ManageKitBi.php
	 * @param {?object} opt_params Object of additional params. Supported: 'value' - to use in Google Analytics 'value' param.
	 *     'code_value' - a string to replace a '%s' placeholder in event action. For example see event 'System_Monetization_MyBalanceBuy'
	 *     0 => Failure ( NEW )
	 *     1 => Success ( NEW )
	 *     2 => Failure ( UPDATE )
	 *     3 => Success ( UPDATE )
	 *     4 => Failure ( DELETE )
	 *     5 => Success ( DELETE )
	 *     6 => Failure ( GET )
	 *     7 => Success ( GET )
	 *     8 => Failure ( Other )
	 *     9 => Success ( Other )
	 *     @param {?function} opt_callback Callback function, returns success/failed data.
	 */
	trackEventCode: function(event_code, opt_params, opt_callback) {
	  var eventData = all_bi_events[event_code];
	  var category = '';
	  var action = '';
	  var opt_label = this.userData['shortname'];
	  var opt_value = null;
	  var code_value = null;
	  
	  if (eventData) {
	    // set mandatory params
	    category = eventData['module'];
	    action = eventData['action'];
	    
	    // collect optional params
	    if (opt_params) {	      
	      if (opt_params['value']) {
	        opt_value = opt_params['value'];
        }
	      
	      if (opt_params['code_value']) {
	        action = action.replace('%s', opt_params['code_value']);
        }
	    }
	    if (this.isOutputLog()) {
	      this.log('trackEventCode. category: ' + category + ' action: ' + action + ' opt_value: ' + opt_value);
	    }
	    this.trackEvent(category, action, opt_label, opt_value, opt_callback, event_code);	    
	  } else {
	    this.log('No such event ' + event_code);
	  }	  
	},
	
	/**
	 * Perform Totango tracking
	 */
	trackTotango: function(category, action) {
	  if (this.isTrackTotango()) {
      try {
        if (this.isProd()) {         
          if (!totangoTracker) {
            this.addEventToQueue(category, action, true);
          } else {                                
            // Track event in Totango       
            totangoTracker.track(action, category);
            if (this.isOutputLog()) {
              this.log('Tracking Totango >> Module: ' + category + ' Action: ' + action + ' User: ' + totangoTracker.getUser() + ' Org: ' + totangoTracker.getOrg());
            }
          }           
        }        
      } catch(err) {      
        ManageKitUtils.log('Totango event tracking failed. ' + err);
      }
    }
	},
	
	/**
	 * Perform Google tracking
	 */
	trackGoogle: function(category, action, opt_label, opt_value) {
	  if (this.isTrackGoogle()) {
      try {
        if (this.isProd()) {        
          // Build Google Analytics tracking params
          var gaParams = ['_trackEvent', category, action];
          if (opt_label) {
            gaParams.push(opt_label);
          }
          
          if (opt_value) {
            gaParams.push(parseInt(opt_value, 10));
          }
                          
          // Track event in Google Analytics        
          _gaq.push(gaParams);
          if (this.isOutputLog()) {
            this.log('Tracking Google >> Module: ' + category + ' Action: ' + action + ' Label: ' + opt_label + ' Value: ' + opt_value);
          }
        }               
      } catch(err) {
        this.log('Google Analytics event tracking failed. ' + err);
      }
    }
	},
	
	/**
	 * Perform SohoOS BI tracking
	 */
	trackSohoOS: function(event_code, opt_value, opt_callback) {
	  if (this.isTrackSohoOS()) {
      try {
        if (this.isStaging()) {
          if (!opt_callback) {
            opt_callback = function(data) {};
          }
          if (!opt_value) {
            opt_value = '';
          }
          this.trackSohoOSBi(event_code, opt_value, opt_callback);
          if (this.isOutputLog()) {
            this.log('Tracking SohoOS >> Event code: ' + event_code +  ' Value: ' + opt_value);
          }
        }        
      } catch(err) {     
        ManageKitUtils.log('SohoOS BI event tracking failed. ' + err);
      }       
    }
	},
	
	/**
	 * Track an event, using SohoOS BI system
	 *
	 * @param {!string} event_code The code of the event in ManageKitBi.php	 
   * @param {?number} opt_value Event additional numeric value.
   * @param {?function} opt_callback Callback function, returns success/failed data.
	 */
	trackSohoOSBi: function(event_code, opt_value, opt_callabck) {
	  var user_data = this.userData;
	  $.ajax({
	    type: "GET",
	    url: ManageKitUtils.SOHOOS_BI_URL,
	    data: {bi_user_id: user_data.user_id,	    	    	    
	      bi_event_code: event_code,
			  bi_data: opt_value},  
	    cache: false,
	    timeout: ManageKitUtils.TIMEOUT_LIMIT_MS,	    
	    success: function(data, textStatus) {			 
			  var ret;
	      if (data == ManageKitUtils.ACTION_OK) {
	        ret = {success: true, message: 'ManageKitUtils.trackSohoOSBi success. ' + data};
	      } else {	        
	        ret = {success: false, message: 'ManageKitUtils.trackSohoOSBi failed. ' + data};
	      }
			  if (opt_callabck) {
			    opt_callabck(ret);			    
			  }
	    },	    	    
	    error: function(request, errorType, errorThrown) {
	      var ret = {success: false, message: 'ManageKitUtils.trackSohoOSBi failed with server error . ' + errorType};
	      if (opt_callabck) {
	        opt_callabck(ret);	 
	      }
	    }
	  });	
	},
  		
	/**
	 * Performs tracking, waits a delay time and then performs a navigational action.
	 * Comes to solve the problem of tracking navigational links.
	 * 
	 * @param {Object} navAction Link object, that was clicked or a javascript command (like form submit)
	 * @param {!string} event_code Code of the event. 
	 */
	trackEventDelayed: function(navAction, event_code) {
		try {
			this.trackEventCode(event_code);
			if (navAction) {
				if (navAction['href']) {
					setTimeout('location.href= "' + navAction.href + '"', this.DELAY_EVENT_MS);
				} else {
					setTimeout(navAction, this.DELAY_EVENT_MS);
				}
			}
		} catch (err) {
			this.log('trackEventDelayed failed. ' + err);
		}
	},		
		
	/**
	 * Sets logged in user data. For non-logged in uses (like the external site), default values are used.
	 * @param {!string} shortname Compnay shortname
	 * @param {!string} vtiger_account_id VTiger account ID
   * @param {!string} user Logged user name
   * @param {!string} user_id Logged user id.
	 */
	setUserData: function(shortname, vtiger_account_id, username, user_id) {
	  this.userData.shortname = shortname;
	  this.userData.vtiger_account_id = vtiger_account_id;
	  this.userData.username = username;
	  this.userData.user_id = user_id; 
	  
	  // Set Totango user data
	  if (!totangoTracker) {
	    this.addEventToQueue(shortname, username, false);
    } else {
      totangoTracker.identify(shortname, username);
    }
  }
};


if (ManageKitUI == null || typeof(ManageKitUI) != "object") { 
  var ManageKitUI = {};
}

ManageKitUI.Consts = {
  IMAGES_PATH: '/crm/managekit/static/images/ui/'
};

ManageKitUI.BgColors = {
  BLACK: 'black',
  YELLOW: 'yellow',
  GREEN: 'green',
  BLUE: 'blue',
  DARKGREEN: 'darkgreen',
  LIGHTGREEN: 'lightgreen',
  LIGHTYELLOW : 'lightyallow',
  LIGHTRED: 'lightred',
  LIGHTBLUE: 'lightblue',
  DARKYELLOW: 'darkyellow'
  
};

ManageKitUI.TextColors = {
  WHITE: '#ffffff',
  GREEN: '#11AD27',
  DARKGREEN: '#cff7d5',
  LIGHTGREEN: '#1c7128',
  LIGHTYELLOW: '#1c7128',
  DARKBLUE: '#315060'
};

ManageKitUI.TooltipAlign = {
  MIDDLE: 'middle',
  BOTTOM: 'bottom',
  TOP: 'top'
};

/**
 * Vertical tooltip
 * @param {object} el The element we add the tooltip to.
 */
ManageKitUI.VerticalTooltip = function(el) {
  this.OFFSET_LEFT = 26;
  this.MARGIN_LEFT_TOOLTIP = 20;
  this.MARGIN_RIGHT_TOOLTIP = 55;
  
  /**
   * Creates the tooltip
   */
  this.create = function() {
    this.el = el;
    this.tooltip = $('<div class="black_tooltip"><div class="tooltip_left fl_bal"></div><div class="tooltip_center fl_bal"><span></span></div><div class="tooltip_right fl_bal"></div><div class="tooltip_arrow"></div></div>');
    $('body').append(this.tooltip);
  };
  
  /**
   * Displays the tooltip
   * @param {!string} html HTML content of the tooltip
   */
  this.display = function(html) {
    this.create();
    $('.tooltip_center span', this.tooltip).html(html);
    var tooltipWidth = this.tooltip.outerWidth() + this.OFFSET_LEFT;
    var screenWidth =  window.screen.width;
    var left = this.el.offset().left;
    var top = this.el.offset().top - this.tooltip.height();

    // Find if the "Left" tooltip exceeds the screen
    // If it is - show "Right" tooltip
    if ((left + tooltipWidth) > screenWidth) {
      left = (left + this.el.outerWidth()) - tooltipWidth + this.OFFSET_LEFT;
      $('.tooltip_arrow', this.tooltip).css('margin-left', tooltipWidth - this.MARGIN_RIGHT_TOOLTIP);
    } else {
      $('.tooltip_arrow', this.tooltip).css('margin-left', this.MARGIN_LEFT_TOOLTIP);
    }

    this.tooltip.css({'left': left, 'top': top, 'width': tooltipWidth});
    this.tooltip.show();
  };
  
  /**
   * Hides the tooltip
   */
  this.hide = function() {
    this.tooltip.hide();
    this.tooltip.remove();
  };
};

/**
 * Horizontal tooltip
 * @param {!Object} el The element we create the tooltip to.
 */
ManageKitUI.HorizontalTooltip = function(el) {
  this.el = el;
  this.ARROW_HEIGHT = 10;
  this.ARROW_MARGIN = 3;
  this.displayed = false;

  /**
   * Creates the tooltip.
   * @param {!string} text The text inside the tooltip.
   * @param {?ManageKitUI.BgColors} bg_color The color of the tooltip.
   * @param {?ManageKitUI.TextColors} text_color The color of the text in the tooltip.
   */
  this.create = function(html, align, bg_color, text_color) {
    this.tooltip = $('<div class="mk_ui_horizontal_tooltip"><div class="fl_bal"><div class="mk_ui_horizontal_tooltip_top"></div><div class="mk_ui_horizontal_tooltip_center"><div class="mk_ui_horizontal_tooltip_text"></div></div><div class="mk_ui_horizontal_tooltip_bottom"></div></div><div class="mk_ui_horizontal_tooltip_arrow_right fl_bal"></div></div>');
    $('body').append(this.tooltip);
    
    // set HTML content
    $('.mk_ui_horizontal_tooltip_text', this.tooltip).html(html);
    $('.mk_ui_horizontal_tooltip_text', this.tooltip).css({'color': text_color});

    var elOffset = this.el.offset();    
    var newLeft = elOffset.left - this.tooltip.width() - this.ARROW_MARGIN;
    var newTop = elOffset.top;
	
    // set color
    $('.mk_ui_horizontal_tooltip_top', this.tooltip).css({'background-image': 'url(\''+ ManageKitUI.Consts.IMAGES_PATH + 'tooltip/htooltop_' + bg_color + '_top.png' +'\')'});    
    $('.mk_ui_horizontal_tooltip_center', this.tooltip).css({'background-image': 'url(\''+ ManageKitUI.Consts.IMAGES_PATH + 'tooltip/htooltop_' + bg_color + '_center.png' +'\')'});
    $('.mk_ui_horizontal_tooltip_bottom', this.tooltip).css({'background-image': 'url(\''+ ManageKitUI.Consts.IMAGES_PATH + 'tooltip/htooltop_' + bg_color + '_bottom.png' +'\')', 'background-position': '0 bottom'});
    $('.mk_ui_horizontal_tooltip_arrow_right', this.tooltip).css({'background-image': 'url(\''+ ManageKitUI.Consts.IMAGES_PATH + 'tooltip/htooltop_' + bg_color + '_arrow.png' +'\')'});   
    
    var tooltipHeight = this.tooltip.height();    
    var elHeight = this.el.height();
    // if the element has a border - calculate with a border
    if (parseInt(this.el.css('border-bottom-width'), 10) > 0 || parseInt(this.el.css('border-top-width'), 10) > 0) {
      elHeight = this.el.outerHeight();
    }
    var arrowMargin = this.ARROW_HEIGHT;
    
    // locate the tooltip and the arrow
    switch (align) {
      case ManageKitUI.TooltipAlign.MIDDLE:
        if (tooltipHeight > elHeight) {
          newTop = elOffset.top - ((tooltipHeight - elHeight) /2)
        } else {
          newTop = ((elHeight - tooltipHeight) /2) + elOffset.top;
        }
        arrowMargin = (tooltipHeight - this.ARROW_HEIGHT) / 2;
        break;
        
      case ManageKitUI.TooltipAlign.TOP:
        newTop = elOffset.top;
        if (tooltipHeight > elHeight) {          
          arrowMargin = (elHeight - this.ARROW_HEIGHT) / 2;
        } else {          
          arrowMargin = this.ARROW_HEIGHT;
        }
        break;
        
      case ManageKitUI.TooltipAlign.BOTTOM:
        if (tooltipHeight > elHeight) {
          newTop = elOffset.top - (tooltipHeight - elHeight);
          arrowMargin = (tooltipHeight - this.ARROW_HEIGHT) - ((elHeight - this.ARROW_HEIGHT) / 2);
        } else {
          newTop = elOffset.top + (elHeight - tooltipHeight);
          arrowMargin = tooltipHeight - (this.ARROW_HEIGHT * 2);
        }
        break;
    }
    
    // Just in case - check the values
    if (newTop < 0) {
      //newTop = 0;
    }    
    if (arrowMargin > tooltipHeight) {
      arrowMargin = this.ARROW_HEIGHT;
    }
    this.tooltip.css({left: newLeft, top: newTop});
    $('.mk_ui_horizontal_tooltip_arrow_right', this.tooltip).css({'margin-top': arrowMargin});

  };
  
  /**
   * Displays the tooltip.
   * @param {!string} text The text inside the tooltip.
   * @param {?ManageKitUI.BgColors} opt_bg_color The color of the tooltip. Default is Black.
   * @param {?ManageKitUI.TextColors} opt_text_color The color of the text in the tooltip. Default is White.
   */
  this.display = function(html, opt_align, opt_bg_color, opt_text_color) {
    if (this.displayed) {
      this.hide();
    }
    
    if (!opt_align) {
      opt_align = ManageKitUI.TooltipAlign.MIDDLE;
    }
    
    if (!opt_bg_color) {
      opt_bg_color = ManageKitUI.BgColors.BLACK;
    }
    
    if (!opt_text_color) {
      opt_text_color = ManageKitUI.TextColors.WHITE;
    }
             
    this.create(html, opt_align, opt_bg_color, opt_text_color);
    this.displayed = true;
    this.tooltip.fadeIn(200);
  };
  
  /**
   * Hides the tooltip
   */
  this.hide = function() {
    this.displayed = false;
    if (this.tooltip) {      
      this.tooltip.hide();
      this.tooltip.remove();
    }
  };
  
  /**
   * Check if the tooltip is shown.
   * @return {boolean} True if the tooltip is shown, false if not
   */
  this.isDisplayed = function() {
    return this.displayed;
  };
};


