/*global Modernizr:true*/
/*global assetPath:true*/

/**
  The main Discourse Application

  @class Discourse
  @extends Ember.Application
**/
Discourse = Ember.Application.createWithMixins({
  rootElement: '#main',

  // Data we want to remember for a short period
  transient: Em.Object.create(),

  // Whether the app has focus or not
  hasFocus: true,

  // Are we currently scrolling?
  scrolling: false,

  // The highest seen post number by topic
  highestSeenByTopic: {},

  getURL: function(url) {

    // If it's a non relative URL, return it.
    if (url.indexOf('http') === 0) return url;

    var u = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri);
    if (u[u.length-1] === '/') {
      u = u.substring(0, u.length-1);
    }
    return u + url;
  },

  titleChanged: function() {
    var title;
    title = "";
    if (this.get('title')) {
      title += "" + (this.get('title')) + " - ";
    }
    title += Discourse.SiteSettings.title;
    $('title').text(title);
    if (!this.get('hasFocus') && this.get('notify')) {
      title = "(*) " + title;
    }
    // chrome bug workaround see: http://stackoverflow.com/questions/2952384/changing-the-window-title-when-focussing-the-window-doesnt-work-in-chrome
    window.setTimeout(function() {
      document.title = ".";
      document.title = title;
    }, 200);
  }.observes('title', 'hasFocus', 'notify'),

  currentUserChanged: function() {

    // We don't want to receive any previous user notifications
    var bus = Discourse.MessageBus;
    bus.unsubscribe("/notification/*");
    bus.callbackInterval = Discourse.SiteSettings.anon_polling_interval;
    bus.enableLongPolling = false;

    var user = this.get('currentUser');
    if (user) {
      bus.callbackInterval = Discourse.SiteSettings.polling_interval;
      bus.enableLongPolling = true;
      if (user.admin || user.moderator) {
        bus.subscribe("/flagged_counts", function(data) {
          user.set('site_flagged_posts_count', data.total);
        });
      }
      bus.subscribe("/notification/" + user.id, (function(data) {
        user.set('unread_notifications', data.unread_notifications);
        user.set('unread_private_messages', data.unread_private_messages);
      }), user.notification_channel_position);
      bus.subscribe("/categories", function(data){
        Discourse.get('site').set('categories', data.categories.map(function(c){
          return Discourse.Category.create(c);
        }));
      });
    }
  }.observes('currentUser'),

  // The classes of buttons to show on a post
  postButtons: function() {
    return Discourse.SiteSettings.post_menu.split("|").map(function(i) {
      return (i.replace(/\+/, '').capitalize());
    });
  }.property('Discourse.SiteSettings.post_menu'),

  notifyTitle: function() {
    this.set('notify', true);
  },

  openComposer: function(opts) {
    // TODO, remove container link
    var composer = Discourse.__container__.lookup('controller:composer');
    if (composer) composer.open(opts);
  },

  /**
    Establishes global DOM events and bindings via jQuery.

    @method bindDOMEvents
  **/
  bindDOMEvents: function() {
    var $html, hasTouch;

    $html = $('html');
    hasTouch = false;

    if ($html.hasClass('touch')) {
      hasTouch = true;
    }

    if (Modernizr.prefixed("MaxTouchPoints", navigator) > 1) {
      hasTouch = true;
    }

    if (hasTouch) {
      $html.addClass('discourse-touch');
      this.touch = true;
      this.hasTouch = true;
    } else {
      $html.addClass('discourse-no-touch');
      this.touch = false;
    }

    $('#main').on('click.discourse', '[data-not-implemented=true]', function(e) {
      e.preventDefault();
      alert(Em.String.i18n('not_implemented'));
      return false;
    });

    $('#main').on('click.discourse', 'a', function(e) {
      if (e.isDefaultPrevented() || e.shiftKey || e.metaKey || e.ctrlKey) return;

      var $currentTarget = $(e.currentTarget);
      var href = $currentTarget.attr('href');
      if (!href) return;
      if (href === '#') return;
      if ($currentTarget.attr('target')) return;
      if ($currentTarget.data('auto-route')) return;

      // If it's an ember #linkTo skip it
      if ($currentTarget.hasClass('ember-view')) return;

      if ($currentTarget.hasClass('lightbox')) return;
      if (href.indexOf("mailto:") === 0) return;
      if (href.match(/^http[s]?:\/\//i) && !href.match(new RegExp("^http:\\/\\/" + window.location.hostname, "i"))) return;

      e.preventDefault();
      Discourse.URL.routeTo(href);
      return false;
    });

    $(window).focus(function() {
      Discourse.set('hasFocus', true);
      Discourse.set('notify', false);
    }).blur(function() {
      Discourse.set('hasFocus', false);
    });

    // Add a CSRF token to all AJAX requests
    var csrfToken = $('meta[name=csrf-token]').attr('content');
    $.ajaxPrefilter(function(options, originalOptions, xhr) {
      if (!options.crossDomain) {
        xhr.setRequestHeader('X-CSRF-Token', csrfToken);
      }
    });
  },

  /**
    Log the current user out of Discourse

    @method logout
  **/
  logout: function() {
    Discourse.KeyValueStore.abandonLocal();
    Discourse.ajax("/session/" + this.get('currentUser.username'), {
      type: 'DELETE'
    }).then(function() {
      // Reloading will refresh unbound properties
      window.location.reload();
    });
  },

  authenticationComplete: function(options) {
    // TODO, how to dispatch this to the view without the container?
    var loginView = Discourse.__container__.lookup('controller:modal').get('currentView');
    return loginView.authenticationComplete(options);
  },

  /**
    Our own $.ajax method. Makes sure the .then method executes in an Ember runloop
    for performance reasons. Also automatically adjusts the URL to support installs
    in subfolders.

    @method ajax
  **/
  ajax: function() {

    var url, args;
    if (arguments.length === 1) {
      if (typeof arguments[0] === "string") {
        url = arguments[0];
        args = {};
      } else {
        args = arguments[0];
        url = args.url;
        delete args.url;
      }
    } else if (arguments.length === 2) {
      url = arguments[0];
      args = arguments[1];
    }

    if (args.success) {
      console.warning("DEPRECATION: Discourse.ajax should use promises, received 'success' callback");
    }
    if (args.error) {
      console.warning("DEPRECATION: Discourse.ajax should use promises, received 'error' callback");
    }

    return Ember.Deferred.promise(function (promise) {
      var oldSuccess = args.success;
      args.success = function(xhr) {
        Ember.run(promise, promise.resolve, xhr);
        if (oldSuccess) oldSuccess(xhr);
      }

      var oldError = args.error;
      args.error = function(xhr) {

        // If it's a parseerror, don't reject
        if (xhr.status === 200) return args.success(xhr);

        promise.reject(xhr);
        if (oldError) oldError(xhr);
      }

      // We default to JSON on GET. If we don't, sometimes if the server doesn't return the proper header
      // it will not be parsed as an object.
      if (!args.type) args.type = 'GET';
      if ((!args.dataType) && (args.type === 'GET')) args.dataType = 'json';

      $.ajax(Discourse.getURL(url), args);
    });
  },

  /**
    Start up the Discourse application.

    @method start
  **/
  start: function() {
    Discourse.bindDOMEvents();
    Discourse.SiteSettings = PreloadStore.get('siteSettings');
    Discourse.MessageBus.alwaysLongPoll = Discourse.Environment === "development";
    Discourse.MessageBus.start();
    Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus);
    // Make sure we delete preloaded data
    PreloadStore.remove('siteSettings');
    // Developer specific functions
    Discourse.Development.setupProbes();
    Discourse.Development.observeLiveChanges();
  }

});

Discourse.Router = Discourse.Router.reopen({ location: 'discourse_location' });