'use strict';

(function(){
  var REQUIRED_FIELDS = ['hitType','eventCategory','eventAction'];
  var ALLOWED_HIT_TYPES = ['pageview','screenview','event','transaction','item','social','exception','timing'];

  angular
    .module('habitrpg')
    .factory('Analytics', analyticsFactory);

  analyticsFactory.$inject = [
    'User'
  ];

  function analyticsFactory(User) {

    var user = User.user;

    // Amplitude
    var r = window.amplitude || {};
    r._q = [];
    function a(window) {r[window] = function() {r._q.push([window].concat(Array.prototype.slice.call(arguments, 0)));}}
    var i = ["init", "logEvent", "logRevenue", "setUserId", "setUserProperties", "setOptOut", "setVersionName", "setDomain", "setDeviceId", "setGlobalUserProperties"];
    for (var o = 0; o < i.length; o++) {a(i[o])}
    window.amplitude = r;
    amplitude.init(window.env.AMPLITUDE_KEY, user ? user._id : undefined);

    // Google Analytics (aka Universal Analytics)
    window['GoogleAnalyticsObject'] = 'ga';
    window['ga'] = window['ga'] || function() {
        (window['ga'].q = window['ga'].q || []).push(arguments)
      }, window['ga'].l = 1 * new Date();
    ga('create', window.env.GA_ID, user ? {'userId': user._id} : undefined);

    function loadScripts() {
      setTimeout(function() {
        // Amplitude
        var n = document.createElement("script");
        var s = document.getElementsByTagName("script")[0];
        n.type = "text/javascript";
        n.async = true;
        n.src = "https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.2.0-min.gz.js";
        s.parentNode.insertBefore(n, s);

        // Google Analytics
        var a = document.createElement('script');
        var m = document.getElementsByTagName('script')[0];
        a.async = 1;
        a.src = '//www.google-analytics.com/analytics.js';
        m.parentNode.insertBefore(a, m);
      });
    }

    function register() {
      setTimeout(function() {
        amplitude.setUserId(user._id);
        ga('set', {'userId':user._id});
      });
    }

    function login() {
      setTimeout(function() {
        amplitude.setUserId(user._id);
        ga('set', {'userId':user._id});
      });
    }

    function track(properties) {
      setTimeout(function() {
        if(_doesNotHaveRequiredFields(properties)) { return false; }
        if(_doesNotHaveAllowedHitType(properties)) { return false; }

        amplitude.logEvent(properties.eventAction,properties);
        ga('send',properties);
      });
    }

    function updateUser(properties) {
      setTimeout(function() {
        properties = properties || {};

        _gatherUserStats(user, properties);

        amplitude.setUserProperties(properties);
        ga('set',properties);
      });
    }

    if (window.env.NODE_ENV === 'production') loadScripts();

    return {
      loadScripts: loadScripts,
      register: register,
      login: login,
      track: track,
      updateUser: updateUser
    };
  }

  function _gatherUserStats(user, properties) {
    if (user._id) properties.UUID = user._id;
    if (user.stats) {
      properties.Class = user.stats.class;
      properties.Experience = Math.floor(user.stats.exp);
      properties.Gold = Math.floor(user.stats.gp);
      properties.Health = Math.ceil(user.stats.hp);
      properties.Level = user.stats.lvl;
      properties.Mana = Math.floor(user.stats.mp);
    }
    properties.tutorialComplete = user.flags && user.flags.tour && user.flags.tour.intro === -2;
    if (user.habits && user.dailys && user.todos && user.rewards) {
      properties["Number Of Tasks"] = {
        habits: user.habits.length,
        dailys: user.dailys.length,
        todos: user.todos.length,
        rewards: user.rewards.length
      };
    }
    if (user.contributor && user.contributor.level) properties.contributorLevel = user.contributor.level;
    if (user.purchased && user.purchased.plan.planId) properties.subscription = user.purchased.plan.planId;
  }

  function _doesNotHaveRequiredFields(properties) {
    if (!_.isEqual(_.keys(_.pick(properties, REQUIRED_FIELDS)), REQUIRED_FIELDS)) {
      console.log('Analytics tracking calls must include the following properties: ' + JSON.stringify(REQUIRED_FIELDS));
      return true;
    }
  }

  function _doesNotHaveAllowedHitType(properties) {
    if (!_.contains(ALLOWED_HIT_TYPES, properties.hitType)) {
      console.log('Hit type of Analytics event must be one of the following: ' + JSON.stringify(ALLOWED_HIT_TYPES));
      return true;
    }
  }
}());
