window.Guanoo = {
  init: function(){
    $('body').bind('click', function (e) {
      $('.dropdown-toggle, .menu').parent('li').removeClass('open');
    });
    $('.dropdown-toggle, .menu').click(function (e) {
      var $li = $(this).parent('li').toggleClass('open');
      return false;
    });
  },
  go: function(path){
    window.location.href = '/' + path;
  },
  page: function(){
    return new String(window.location.pathname).substr(1);
  },
  decode: decodeURIComponent,
  encode: encodeURIComponent,
  version: 0.1
};

window.Guanoo.Cookie = {
  set: function(name, value, hours) {
    var cookie = 'AdReturns_' + name + '=' + Guanoo.encode(value) + '; path=/'
    if (hours) {
      var expires = new Date();
      expires.setTime(expires.getTime() + hours*60*60*1000);
      cookie += '; expires=' + expires.toGMTString();
    }
    document.cookie = cookie;
    return value;
  },
  get: function(name)
  {
    var cookie = document.cookie;
    var prefix = 'AdReturns_' + name + '=';
    var begin = cookie.indexOf('; ' + prefix);
    if (begin == -1) {
      begin = cookie.indexOf(prefix);
      if (begin != 0) return '';
    }
    else begin += 2;
    var end = document.cookie.indexOf(';', begin);
    if (end == -1) end = cookie.length;
    return Guanoo.decode(cookie.substring(begin + prefix.length, end));
  }
};

window.Guanoo.Link = {
  is_available: false,
  bind_create_events: function(){
    $('input#link_name, input#link_path, input#link_destination').blur( this.has_input );
    $('select#link_domain').change( this.check_available );
    $('input#link_path').blur( this.check_available );
    if ($('input#link_path').attr('value')) this.check_available();
  },
  check_available: function(e){
    var domain = $('select#link_domain').attr('value'),
        path = $('input#link_path').attr('value');
    if (path.length < 4){
      $('#link_path_info').html("&larr; Sorry, it's too short");
      $('input#link_path').addClass('red-border');
      return;
    };
    Guanoo.Link.find(domain, path, function(link){
      var info = '&larr; ' + (link.id ? 'Sorry, it\'s <a href="/link/info?id='+link.id+'">taken</a>' : 'Good choice!');
      $('#link_path_info').html(info);
      if (link.id) $('input#link_path').addClass('red-border');
      else $('input#link_path').removeClass('red-border');
      Guanoo.Link.is_available = link.id ? false : true;
    });
  },
  create_validate: function(form){
    var $dest = $('input#link_destination'),
        $path = $('input#link_path'),
        $name = $('input#link_name');
    if (!this.has_input($dest) ||
        !this.has_input($path) ||
        !this.has_input($name)) return false;
    if (window.form_script) window.form_script(form);
    return this.is_available;
  },
  find: function(domain, path, cb){
    $.get('/link/find.json',
          {'link->domain':domain, 'link->path':path},
          function(link){ cb(link) }, 'json');
  },
  has_input: function($field){ // param can be a $field or an event
    if ($field.target) $field = $($field.target);
    var value = $field.attr('value');
    if (value == '') $field.addClass('red-border');
    else $field.removeClass('red-border');
    return value;
  },
  version: 0.1
};

window.Guanoo.Link.Clicks = {
  my_sig: null,
  clicks: null,
  totals: null,
  chart: null,
  data: null,
  show: '',
  type: '',
  init: function(id, show){
    var self = this;
    self.bind_report_events();
    $.get('/link/clicks.json',
          {id:id, html:1},
          function(data){
            self.my_sig = data.my_sig;
            self.clicks = data.clicks;
            self.totals = data.totals;
            self.bind_data();
            if (show) self[show](self.filter());
          }, 'json');
  },
  bind_report_events: function(){
    var self = this,
        report = function(e, name){ self.select_report(e, name); return false },
        filter = function(type){ return self.filter(type) },
        show = function(clicks){ self[self.show](clicks); return false };
    $('li#report-details a').click(function(e){return report(e, 'details')});
    $('li#report-trends a').click(function(e){return report(e, 'trends')});
    $('li#report-browsers a').click(function(e){return report(e, 'browsers')});
    $('li#report-systems a').click(function(e){return report(e, 'systems')});
    $('li#report-locations a').click(function(e){return report(e, 'locations')});
    $('li#report-languages a').click(function(e){return report(e, 'languages')});
    $('li#report-referrers a').click(function(e){return report(e, 'referrers')});
    $('ul#click-types li#all a').click(function(){return show(filter('all'))});
    $('ul#click-types li#pc a').click(function(){return show(filter('pc'))});
    $('ul#click-types li#mobile a').click(function(){return show(filter('mobile'))});
    $('ul#click-types li#bots a').click(function(){return show(filter('bots'))});
    this.type = Guanoo.Cookie.get('click-type');
  },
  bind_data: function(){
    var ex = (Guanoo.Cookie.get('exclude-me') == 'Y');
    var self = this, totals = this.totals, dataModel = {
      items: ko.observableArray(this.clicks),
      exclude_me: ko.observable(ex),
      total_me: ko.observable(totals.me.all),
      total_all: ko.observable(ex ? totals.all-totals.me.all : totals.all),
      total_pc: ko.observable(ex ? totals.pc-totals.me.pc : totals.pc),
      total_mobile: ko.observable(ex ? totals.mobile-totals.me.mobile : totals.mobile),
      total_robots: ko.observable(ex ? totals.robots-totals.me.robots : totals.robots)
    };
    if (totals.me.all) $('.exclude-me').show();
    dataModel.exclude_me.subscribe(function(ex){
      var data = self.data, totals = self.totals;
      data.total_all(ex ? totals.all-totals.me.all : totals.all);
      data.total_pc(ex ? totals.pc-totals.me.pc : totals.pc);
      data.total_mobile(ex ? totals.mobile-totals.me.mobile : totals.mobile);
      data.total_robots(ex ? totals.robots-totals.me.robots : totals.robots);
      if (self.show) self[self.show](self.filter());
      Guanoo.Cookie.set('exclude-me', ex ? 'Y':'N');
    });
    dataModel.clicksGrid = new ko.simpleGrid.viewModel({
      data: dataModel.items,
      columns: [
        { headerText: 'Time (US EST)', rowText: 'html_time' },
        { headerText: 'Device', rowText: 'html_device' },
        { headerText: 'Location', rowText: 'html_location' },
        { headerText: 'Referrer', rowText: 'html_referrer' }
      ],
      pageSize: 50
    });
    ko.applyBindings(dataModel);
    this.data = dataModel;
  },
  select_report: function(e, name){
    $('ul.tabs li').removeClass('active');
    $(e.target).parent().addClass('active');
    this[name](this.filter());
  },
  details: function(clicks){
    $('#clicks-chart').hide();
    $('#clicks-list').show();
    this.data.items(this.filter());
    this.show = 'details';
  },
  trends: function(clicks){
    var series = $('li#'+this.type+' a').text().replace(/\s*\(\d*\)/, ''),
        title = 'Clicks per day',
        totals = [],
        hour_ms = 1000 * 60 * 60;
    for (i in clicks){
      var time = clicks[i].time - 5 * hour_ms; // EST
      time = parseInt(time / hour_ms / 24) * hour_ms * 24;
      totals[time] = totals[time] || 0;
      totals[time]++;
    }
    Guanoo.Charts.display_time_series({series:series, title:title, totals:totals});
    this.show = 'trends';
  },
  browsers: function(clicks){
    var series = 'Browsers',
        title = 'Web browsers clicking your link',
        totals = [];
    for (i in clicks){
      var browser = clicks[i].browser;
      totals[browser] = totals[browser] || 0;
      totals[browser]++;
    }
    Guanoo.Charts.display_pie_chart({series:series, title:title, totals:totals});
    this.show = 'browsers';
  },
  systems: function(clicks){
    var series = 'Operating systems',
        title = 'Operating systems clicking your link',
        totals = [];
    for (i in clicks){
      var op_sys = clicks[i].op_sys;
      totals[op_sys] = totals[op_sys] || 0;
      totals[op_sys]++;
    }
    Guanoo.Charts.display_pie_chart({series:series, title:title, totals:totals});
    this.show = 'systems';
  },
  locations: function(clicks){
    var series = 'Locations',
        title = 'Locations of people clicking your link',
        totals = [];
    for (i in clicks){
      var loc = '', row = clicks[i];
      if (row.city) loc += row.city;
      if (row.region) loc += ' ' + row.region;
      if (row.country_name){
        if (loc) loc += ', ';
        loc += row.country_name;
      }
      if (loc == '') loc = 'unknown';
      totals[loc] = totals[loc] || 0;
      totals[loc]++;
    }
    Guanoo.Charts.display_pie_chart({series:series, title:title, totals:totals});
    this.show = 'locations';
  },
  languages: function(clicks){
    var series = 'Languages',
        title = 'Languages of people clicking your link',
        totals = [];
    for (i in clicks){
      var language = clicks[i].language || 'unknown';
      totals[language] = totals[language] || 0;
      totals[language]++;
    }
    Guanoo.Charts.display_pie_chart({series:series, title:title, totals:totals});
    this.show = 'languages';
  },
  referrers: function(clicks){
    var series = 'Referrers',
        title = 'URLs referring clicks via your link',
        totals = [];
    for (i in clicks){
      var referrer = clicks[i].referrer || 'unknown';
      totals[referrer] = totals[referrer] || 0;
      totals[referrer]++;
    }
    Guanoo.Charts.display_pie_chart({series:series, title:title, totals:totals});
    this.show = 'referrers';
  },
  filter: function(type){
    var filtered = [], clicks = this.clicks,
        exclude_me = this.data.exclude_me();
    type = type || this.type || 'all';
    $('ul#click-types li').removeClass('active');
    $('ul#click-types li#'+type).addClass('active');
    for (i in clicks){
      var click = clicks[i],
          is_mobile = (click.is_mobile == 'Y'),
          is_robot = (click.is_robot == 'Y'),
          push = false;
      if (exclude_me && click.visitor_sig == this.my_sig) continue;
      if (type == 'all') push = true;
      else if (type == 'pc' && !is_mobile && !is_robot) push = true;
      else if (type == 'mobile' && is_mobile && !is_robot) push = true;
      else if (type == 'bots' && is_robot) push = true;
      if (push) filtered.push(click);
    }
    this.type = Guanoo.Cookie.set('click-type', type);
    return filtered;
  },
  version: 0.1
}

Guanoo.Charts = {
  display_pie_chart: function(opts){
    $('#clicks-list').hide();
    $('#clicks-chart').show();
    var formatter = function(){
      return '<b>' + this.point.name + '</b> ' + parseInt(this.percentage) + '%';
    };
    var formatter_trunc = function(){
      var name = this.point.name;
      if (name.length > 20) name = name.substr(0, 20) + '...';
      return '<b>' + name + '</b> ' + parseInt(this.percentage) + '%';
    };
    var sorted = this.sort_totals_by_value(opts.totals);
    this.chart = new Highcharts.Chart({
      chart: { renderTo: 'clicks-chart' },
      title: { text: opts.title },
      tooltip: { formatter: formatter },
      plotOptions: {
        pie: {
          allowPointSelect: true,
          cursor: 'pointer',
          dataLabels: {
            enabled: true,
            color: '#000000',
            connectorColor: '#000000',
            formatter: formatter_trunc
          },
          showInLegend: sorted.length == 1
        }
      },
      series: [{ type: 'pie', name: opts.series, data: sorted }]
    });
  },
  display_time_series: function(opts){
    $('#clicks-list').hide();
    $('#clicks-chart').show();
    var sorted = this.sort_totals_by_key(this.time_series_zeros(opts.totals));
    this.chart = new Highcharts.Chart({
      chart: { renderTo: 'clicks-chart' },
      title: { text: opts.title },
      xAxis: {
        type: 'datetime',
        tickInterval: 24 * 3600 * 1000, // one day
        gridLineWidth: 1,
        labels: {
          align: 'left'
        }
      },
      yAxis: [{
        title: {text: null},
        labels: {
          align: 'left',
          formatter: function() {
            return Highcharts.numberFormat(this.value, 0);
          }
        },
        showFirstLabel: false,
        allowDecimals: false,
        min: 0
      }],
      plotOptions: {
        series: {
          cursor: 'pointer'
        }
      },
      series: [{
        name: opts.series,
        data: sorted,
        lineWidth: 4,
        marker: {radius: 4}
      }]
    });
  },
  time_series_zeros: function(totals){
    var min = 9999999999999, max = 0, time, day_ms = 1000 * 60 * 60 * 24;
    for (var key in totals){
      time = parseInt(key);
      if (time < min) min = time;
      if (time > max) max = time;
    }
    for (time = min; time < max; time += day_ms){
      totals[time] = totals[time] || 0;
    }
    return totals;
  },
  sort_totals_by_key: function(totals){
    var list = [];
    for (var key in totals) list.push([parseInt(key), totals[key]]);
    list.sort(function (){return arguments[0][0] < arguments[1][0]});
    return list;
  },
  sort_totals_by_value: function(totals, limit){
    var list = [], others = 0;
    limit = limit || 12; // to keep it pretty!
    for (var key in totals) list.push([key, totals[key]]);
    list.sort(function (){return arguments[0][1] < arguments[1][1]});
    while (list.length > limit){
      var last = list.pop();
      others += last[1];
    }
    if (others) list.push(['Others', others]);
    return list;
  },
  version: 0.1
};

Guanoo.Admin = {
  setup_actions_grid: function(){
    var self = this;
    $.get('/admin/actions.json',
          {}, function(actions){ self.display_actions_grid(actions) }, 'json');
  },
  display_actions_grid: function(actions){
    var actionsModel = {items: ko.observableArray(actions)};
    actionsModel.actionsGrid = new ko.simpleGrid.viewModel({
      data: actionsModel.items,
      columns: [
        { headerText: 'Time', rowText: 'created_at' },
        { headerText: 'Host', rowText: 'host_ip' },
        { headerText: 'Action', rowText: 'action' }
      ],
      pageSize: 20
    });
    ko.applyBindings(actionsModel);
  },
  version: 0.1
};

// End of guanoo.js

