/*global assetPath:true */

/**
  This controller supports the pop up quote button

  @class QuoteButtonController
  @extends Discourse.Controller
  @namespace Discourse
  @module Discourse
**/
Discourse.QuoteButtonController = Discourse.Controller.extend({
  needs: ['topic', 'composer'],

  init: function() {
    this._super();
    $LAB.script(assetPath('defer/html-sanitizer-bundle'));
  },

  /**
    If the buffer is cleared, clear out other state (post)
  **/
  bufferChanged: function() {
    if (this.blank('buffer')) this.set('post', null);
  }.observes('buffer'),

  /**
    Save the currently selected text and displays the
    "quote reply" button

    @method selectText
  **/
  selectText: function(postId) {
    // anonymous users cannot "quote-reply"
    if (!Discourse.get('currentUser')) return;
    // don't display the "quote-reply" button if we can't create a post
    if (!this.get('controllers.topic.content.can_create_post')) return;

    var selection = window.getSelection();
    // no selections
    if (selection.rangeCount === 0) return;
    // retrieve the selected range
    var range = selection.getRangeAt(0),
        cloned = range.cloneRange(),
        $ancestor = $(range.commonAncestorContainer);

    // don't display the "quote reply" button if you select text spanning two posts
    // note: the ".contents" is here to prevent selection of the topic summary
    if ($ancestor.closest('.topic-body > .contents').length === 0) return;

    var selectedText = Discourse.Utilities.selectedText();
    if (this.get('buffer') === selectedText) return;

    // we need to retrieve the post data from the posts collection in the topic controller
    var posts = this.get('controllers.topic.posts'),
        length = posts.length,
        post;

    for (var p = 0; p < length; p++) {
      if (posts[p].id === postId) { post = posts[p]; break; }
    }

    this.set('post', post);
    this.set('buffer', selectedText);

    // collapse the range at the beginning of the selection
    // (ie. moves the end point to the start point)
    range.collapse(true);

    // create a marker element containing a single invisible character
    var markerElement = document.createElement("span");
    markerElement.appendChild(document.createTextNode("\ufeff"));
    // insert it at the beginning of our range
    range.insertNode(markerElement);

    // work around chrome that would sometimes lose the selection
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(cloned);

    // move the quote button at the beginning of the selection
    var markerOffset = $(markerElement).offset(),
        $quoteButton = $('.quote-button');

    Em.run.next(function(){
      $quoteButton.offset({
        top: markerOffset.top - $quoteButton.outerHeight() - 5,
        left: markerOffset.left
      });
    });

    // remove the marker
    markerElement.parentNode.removeChild(markerElement);
  },

  /**
    Quote the currently selected text

    @method quoteText
  **/
  quoteText: function() {
    var post = this.get('post');
    var composerController = this.get('controllers.composer');
    var composerOpts = {
      post: post,
      action: Discourse.Composer.REPLY,
      draftKey: this.get('post.topic.draft_key')
    };

    // If the composer is associated with a different post, we don't change it.
    var composerPost = composerController.get('content.post');
    if (composerPost && (composerPost.get('id') !== this.get('post.id'))) {
      composerOpts.post = composerPost;
    }

    var buffer = this.get('buffer');
    var quotedText = Discourse.BBCode.buildQuoteBBCode(post, buffer);
    if (composerController.wouldLoseChanges()) {
      composerController.appendText(quotedText);
    } else {
      composerController.open(composerOpts).then(function() {
        return composerController.appendText(quotedText);
      });
    }
    this.set('buffer', '');
    return false;
  },

  /**
    Deselect the currently selected text

    @method deselectText
  **/
  deselectText: function() {
    // clear selected text
    window.getSelection().removeAllRanges();
    // clean up the buffer
    this.set('buffer', '');
  }

});
