
+function ($) { "use strict";

  // POPOVER PUBLIC CLASS DEFINITION
  // ===============================

  var Editpop = function (element, options) {
    this.einit('editpop', element, options)
  }

  Editpop.DEFAULTS = $.extend({} , $.fn.popover.Constructor.DEFAULTS, {
    container: 'body'
  , trigger: 'manual'
  , placement: function(tip, el) {
    var $tip = $(tip)
    var $el = $(el)

    var tip_width = $tip.width(),
        tip_height = $tip.height(),
        el_width = $el.width(),
        el_height = $el.height(),
        client_width = document.body.clientWidth,
        gap = 20

    var top_gap = $el.offset().top - $("body").scrollTop() - 40,
        left_gap = $el.offset().left - $("body").scrollLeft(),
        right_gap = client_width - left_gap - el_width

    if(top_gap > tip_height + gap && left_gap > tip_width/2 + gap && right_gap > tip_width/2 + gap){
      return 'top'
    }
    if(top_gap > tip_height/2){
      if(right_gap > tip_width + gap){
        return 'right'
      } else if(left_gap > tip_width + gap) {
        return 'left'
      }
    }
    return 'bottom'
  }
  , template: '<div class="popover editpop editable"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  })


  // NOTE: POPOVER EXTENDS tooltip.js
  // ================================

  Editpop.prototype = $.extend({}, $.fn.popover.Constructor.prototype)

  Editpop.prototype.constructor = Editpop

  Editpop.prototype.einit = function (type, element, options) {
    this.init(type, element, options)
    this.content = null
    this.$element.on('click.' + this.type, $.proxy(this.beforeToggle, this))

    this.$text = this.$element.parent().parent().find('.editable-field')
    this.field = this.$element.data('editable-field')
  }

  Editpop.prototype.getDefaults = function () {
    return Editpop.DEFAULTS
  }

  Editpop.prototype.beforeToggle = function() {
    var $el = this.$element

    if(this.content == null){
      var that = this
      $el.find('>i').removeClass('fa fa-edit').addClass('fa fa-spinner fa-spin')
      $.ajax({
        url: $el.data('editable-loadurl'),
        success: function(content){
          $el.find('>i').removeClass('fa fa-spinner fa-spin').addClass('fa fa-edit')
          that.content = content
          that.toggle()
        },
        dataType: 'html'
      })
    } else {
      this.toggle()
    }
  }

  Editpop.prototype.setContent = function () {
    var $tip    = this.tip()
    var title   = this.getTitle()

    $tip.find('.popover-title').html('<button class="close" data-dismiss="editpop">&times;</button>' + title)
    $tip.find('.popover-content').html(this.content)

    var $form = $tip.find('.popover-content > form')
    $form.exform()
    $form.submit($.proxy(this.submit, this))

    this.$form = $form
    this.$mask = $('<div class="mask"><h2 style="text-align:center;"><i class="fa-spinner fa-spin fa fa-large"></i></h2></div>')
    $tip.find('.popover-content').prepend(this.$mask)

    $tip.removeClass('fade top bottom left right in')

    //bind events
    $tip.find('[data-dismiss=editpop]').on('click.' + this.type, $.proxy(this.leave, this, this))

    var me = ((Math.random() * 10) + "").replace(/\D/g, '')
    var click_event_ns = "click." + me + " touchstart." + me
    var that = this

    // $('body').on(click_event_ns, function(e) {
    //   if ( !$tip.has(e.target).length ) { that.hide() }
    // })

    $(document).bind('keyup.editpop', function(e) {
      if (e.keyCode == 27) { that.leave(that) }
      return
    })
  }

  Editpop.prototype.hasContent = function () {
    return this.getTitle() || this.content
  }

  Editpop.prototype.submit = function(e) {
      e.stopPropagation()
      e.preventDefault()
      
      $.when(this.save())
      .done($.proxy(function(data) {
        this.$mask.hide()
        if(data['result'] != 'success' && data['errors']){
          var err_html = []
          for (var i = data['errors'].length - 1; i >= 0; i--) {
            var e = data['errors'][i]
            for (var j = e['errors'].length - 1; j >= 0; j--) {
              err_html.push('<span class="help-block error">'+e['errors'][j]+'</span>')
            }
          }
          this.$form.find(".control-group").addClass('has-error')
          this.$form.find('.controls').append(err_html.join('\n'))
        } else {
          this.$text.html(data['new_html'][this.field])
          this.leave(this)
        }
      }, this))
      .fail($.proxy(function(xhr) {
        this.$mask.hide()
        alert(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
      }, this))
  }

  Editpop.prototype.save = function(newValue) {
    this.$form.find('.control-group').removeClass('has-error')
    this.$form.find('.controls .help-block.error').remove()

    this.$mask.show()

    var off_check_box = Object();
    this.$form.find('input[type=checkbox]').each(function(){
      if(!$(this).is(':checked')){
        off_check_box[$(this).attr('name')] = ''
      }
    })

    return $.ajax({
      data: [this.$form.serialize(), $.param(off_check_box)].join('&'),
      url: this.$form.attr('action'),
      type: "POST",
      dataType: 'json',
      beforeSend: function(xhr, settings) {
          xhr.setRequestHeader("X-CSRFToken", $.getCookie('csrftoken'))
      }
    })
  }

  // POPOVER PLUGIN DEFINITION
  // =========================

  var old = $.fn.editpop

  $.fn.editpop = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.editpop')
      var options = typeof option == 'object' && options

      if (!data) $this.data('bs.editpop', (data = new Editpop(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.editpop.Constructor = Editpop


  // POPOVER NO CONFLICT
  // ===================

  $.fn.editpop.noConflict = function () {
    $.fn.editpop = old
    return this
  }

  $(function(){
    $('.editable-handler').editpop();
  })

}(window.jQuery);
