var replying_to_post_id;
function reply(post_id)
{
	if (replying_to_post_id)
	{
		document.getElementById('answer_to_' + replying_to_post_id).style.display = 'none';
	}

	replying_to_post_id = post_id;
	document.getElementById('answer_to_' + post_id).style.display = 'block';
	document.getElementById('answer_to_' + post_id).getElementsByTagName('textarea')[0].focus();
}
function send_reply(post_id)
{
	if (!is_logged_in_user) { 
		alert('You must be logged in to post.');
		return false;
	}
	if (!is_member) {
		if (group_type == 1) {
			if (confirm('You must be a member to start a new thread. To become a member the group administrator must approve your membership. Would you like to request a membership?')) {
				request_membership();
			}
		} else if(group_type == 2) {
			if (confirm('You must be a member to start a new thread. Would you like to become a member?')) {
				join_group();
			}
		}
		return false;
	}
	
	if (document.getElementById('sending') || document.getElementById('reply_' + post_id).value == '') return;
	var sending = document.createElement('div');
	sending.id = 'sending';
	sending.innerHTML = 'Submitting new post...';
	document.getElementById('answer_to_' + post_id).parentNode.insertBefore(sending, document.getElementById('answer_to_' + post_id));
	
	if(post_id != 'thread'){
		document.getElementById('answer_to_' + post_id).style.display = 'none';
	}
	
	
	$.ajax({
		type: "POST",
		url: "/",
		//data: 'action=send_reply&thread_id=' + thread_id + '&to_post_id=' + post_id + '&post=' + encodeURI(document.getElementById('reply_' + post_id).value),
		data: {action:'send_reply',thread_id:thread_id,to_post_id:post_id,post:$('#reply_' + post_id).val()},
		dataType: 'json',
		success: $.bind(function(post_id, data) {
			if (add_new_posts || (view_style == 'threaded'  && post_id != 'thread'))
			{
				var div = document.createElement('div');
				div.className = 'post';
				div.id = 'post_' + data.post_id;
				div.innerHTML = '<div class="user"><div class="user_data"><a href="#" id="username_post_' + data.post_id + '">'
				+ data.username +
				'</a> (now)</div><div class="post_options">'
				+ '</div></div><div class="text"><p id="post_text_intro_'
				+ data.post_id +
				'">'
				+ (post_id != 'thread' && view_style != 'threaded' ? ('<em>In reply to <a href="#post_' + post_id + '">' + document.getElementById('username_post_' + post_id).innerHTML + '</a>: </em>') : '')
				+ '<span id="post_text_' + data.post_id + '">'
				+ '</span></p><div id="edit_post_'
				+ data.post_id
				+ '" class="edit_post"><textarea name="edit_post" id="edit_post_field_' 
				+ data.post_id +
				'" style="width:100%;" rows="6">'
				+ document.getElementById('reply_' + post_id).value +
				'</textarea><br /><a href="javascript:save_post_edit('
				+ data.post_id +
				')">Save</a></div></div><div class="options"><a href="javascript:reply('
				+ data.post_id +
				')">Reply</a> | <a id="report_spam_'
				+ data.post_id +
				'" href="javascript:report('
				+ data.post_id +
				', \'spam\')">Mark as spam</a> | <a id="report_inappropriate_'
				+ data.post_id +
				'" href="javascript:report('
				+ data.post_id +
				', \'inappropriate\')">Flag as inappropriate</a></div><div class="answer" id="answer_to_'
				+ data.post_id +
				'"><textarea name="reply" id="reply_'
				+ data.post_id +
				'" style="width: 100%;" rows="5"></textarea><input type="button" class="submit" name="post_reply" id="post_reply_'
				+ data.post_id +
				'" value="Post Reply" onclick="send_reply('
				+ data.post_id +
				');" /></div>';

				var childs = document.createElement('div');
				childs.id = 'replies_to_' + data.post_id;
				childs.style.display = 'none';
				div.appendChild(childs);
				if (view_style == 'threaded'  && post_id != 'thread')
				{
					document.getElementById('replies_to_' + post_id).appendChild(div);
					div.style.paddingLeft = (parseInt(document.getElementById('post_' + post_id).style.paddingLeft) + 20) + "px";
					div.style.background = 'url(/xtras/group_arrow.gif) no-repeat ' + (parseInt(document.getElementById('post_' + post_id).style.paddingLeft) + 2) + 'px 4px';
				} else {
					document.getElementById('posts').appendChild(div);
				}
				if (document.getElementById('sending')) document.getElementById('sending').parentNode.removeChild(document.getElementById('sending'));
				location.href = '#post_' + data.post_id;

                                var text = document.createTextNode(document.getElementById('reply_' + post_id).value);
                                document.getElementById('post_text_' + data.post_id).appendChild(text);
                                document.getElementById('post_text_' + data.post_id).innerHTML = document.getElementById('post_text_' + data.post_id).innerHTML.replace(/\n/g, '<br />');
                                document.getElementById('reply_' + post_id).value = '';
				$('#replies_to_' + data.post_id).fadeIn();
			}
			setTimeout(function() { 
				//if(document.getElementById('sending')) document.getElementById('sending').parentNode.removeChild(document.getElementById('sending')); 
				$('#sending').slideUp('normal', function() { $('#sending').remove(); });
			}, 500);
		}, null, post_id)
	});
	
}

function edit_title() {
	$('#title_form').fadeIn();
	$('#title_text').css('display', 'none');
	$('#options').css('display', 'none');
}
function cancel_title() {
	$('#title_form').css('display', 'none');
	$('#title_text').fadeIn();
	$('#options').fadeIn();
}
function save_title()
{
	document.getElementById('title_text').innerHTML = document.getElementById('thread_title').value;
	document.getElementById('title_form').style.display = 'none';
	document.getElementById('options').style.display = 'inline';
	document.getElementById('title_text').style.display = 'inline';
	$.ajax({
		type: "POST",
		url: "/",
		data: 'action=save_title&thread_id=' + thread_id + '&title=' + encodeURI(document.getElementById('thread_title').value) + '&sticky=' + ((document.getElementById('sticky') && document.getElementById('sticky').checked) ? 1 : 0),
		success: function(msg){
		}
	});
}

function delete_thread()
{
	if (confirm('Are you sure you want to delete this thread? The data will be lost and there is no way back'))
	{
		$.ajax({
			type: "POST",
			url: "/",
			data: 'action=delete_thread&thread_id=' + thread_id,
			success: function(msg){
				location.href = '/group/' + group_id + '/';
			}
		});
	}
}

var editing_post_id;
function show_edit_field(post_id)
{
	if (editing_post_id)
	{
		document.getElementById('post_text_intro_' + editing_post_id).style.display = 'block';
		document.getElementById('edit_post_' + editing_post_id).style.display = 'none';
	}
	document.getElementById('post_text_intro_' + post_id).style.display = 'none';
	document.getElementById('edit_post_' + post_id).style.display = 'block';
	editing_post_id = post_id
}
function save_post_edit(post_id)
{
	if (document.getElementById('editing') || document.getElementById('edit_post_field_' + post_id).value == '') return;
	var sending = document.createElement('div');
	sending.id = 'editing';
	sending.appendChild(document.createTextNode('Editing post...'));
	document.getElementById('edit_post_' + post_id).parentNode.insertBefore(sending, document.getElementById('edit_post_' + post_id));
	document.getElementById('post_text_intro_' + post_id).style.display = 'block';
	document.getElementById('edit_post_' + post_id).style.display = 'none';
	document.getElementById('post_text_' + post_id).innerHTML = '';

	var text = document.createTextNode(document.getElementById('edit_post_field_' + post_id).value);
	document.getElementById('post_text_' + post_id).appendChild(text);
	document.getElementById('post_text_' + post_id).innerHTML = document.getElementById('post_text_' + post_id).innerHTML.replace(/\n/g, '<br />');
//	document.getElementById('post_text_' + post_id).innerHTML = (document.getElementById('edit_post_field_' + post_id).value).replace(/\n/g, '<br />');
	
	$.ajax({
		type: "POST",
		url: "/",
		data: 'action=edit_post&thread_id=' + thread_id + '&post_id=' + post_id + '&post=' + encodeURI(document.getElementById('edit_post_field_' + post_id).value),
		success: function(msg){
			setTimeout(function() { document.getElementById('editing').parentNode.removeChild(document.getElementById('editing')); }, 500);
		}
	});
}
function delete_post(post_id)
{
	if (confirm('Are you sure you want to delete this post? The data will be lost and there is no way back'))
	{
		var sending = document.createElement('div');
		sending.id = 'deleting';
		sending.appendChild(document.createTextNode('Deleting post...'));
		document.getElementById('edit_post_' + post_id).parentNode.insertBefore(sending, document.getElementById('edit_post_' + post_id));
		$.ajax({
			type: "POST",
			url: "/",
			data: 'action=delete_post&thread_id=' + thread_id + '&post_id=' + post_id,
			success: function(msg){
				setTimeout(function() {
					document.getElementById('deleting').parentNode.removeChild(document.getElementById('deleting'));
					document.getElementById('post_' + post_id).parentNode.removeChild(document.getElementById('post_' + post_id));
				 }, 500);
			}
		});
	}
}
var reported = { spam: [], inappropriate: [] }

function report(post_id, as)
{
	if (reported[as].indexOf(post_id) > -1)
	{
		return;
	}
	reported[as].push(post_id);

	document.getElementById('report_' + as + '_' + post_id).innerHTML = 'Reported as ' + as;
	$.ajax({
		type: "POST",
		url: "/",
		data: 'action=report_post&thread_id=' + thread_id + '&post_id=' + post_id + '&as=' + as,
		success: function(msg){
			
		}
	});
}




// ==UserScript==
// @name          AutoLink
// @namespace     http://www.squarefree.com/userscripts
// @description   Turns plain text URLs, email addresses, bug numbers, ISBNs, and US phone numbers into links. You can add new filters if you know how to use JavaScript regular expressions.
// ==/UserScript==

/*

  Included filters:

    * Plain text link
    * Email address
    * Bug number (links to bugzilla.mozilla.org)
    * Bug number with comment number
    * ISBN (links to Amazon)
    * US Phone number (creates a callto: link for Skype)

  Features:

    * You can add new filters if you know how to use JavaScript regular expressions.
    * Works even on pages with dynamic content, such as Gmail.
    * Avoids slowing down Firefox.  (Calls setTimeout after working for a while.)
    * Avoids creating self-links.

  Warnings:

    * This triggers a memory leak bug in Firefox (bug 241518).
    * This triggers a dataloss bug in Firefox when editing long Wikipedia pages (bug 315997)

  Author: Jesse Ruderman - http://www.squarefree.com/

  Test page: http://www.squarefree.com/userscripts/test-pages/autolink-test.html

  License: MPL, GPL, LGPL.

  Version history:

    2005-05-25 00:30: Fixed a bug where inserting a leaf made AutoLink re-examine 
                      the entire document from that leaf on.  This slowed down
                      the DHTML at http://www.tiddlywiki.com/, for example.

    2005-05-23 00:20: Use better ISBN regexp from Phil Ringnalda.
                      Exclude "Invite foo@bar.com to Gmail" fake links on Gmail.

    2005-05-22 05:30: Make skipping work correctly.

    2005-05-22 05:00: Use fewer deprecated features of regular expressions.  See
                        http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:RegExp and
                        http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Deprecated_Features

    2005-05-22 01:00: Initial release. See http://www.squarefree.com/2005/05/22/autolink/.

*/


const timeBefore = new Date();


/***********************************
 *             Filters             *
 ***********************************/

/*

  I encourage you to create new filters in your copy of AutoLink. 

  Filters have three fields:

   * name (string)
       Used for tooltip on created links, e.g. "Link added by AutoLink filter: Plain Text Links".
       Used for class attribute of created links, e.g. "autolink autolink-plain-text-links".

   * regexp (regular expression)
       The entire text matching the regular expression will be linked.
       Must be global (/g).
       May be case-insensitive (/i).

   * href (function)
       Arguments: |match|, an output of regexp.exec.  (May also treat RegExp.leftContext, etc. as inputs.)
       Returns: The URL to be used for a link, or |null| to cancel link creation.
       Must not use filter.regexp, but may use other regular expressions.
    
  This regular expression reference might be useful:
  http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:RegExp
  
  If multiple filters match a string, the first filter will win.

*/


const filters = [
  {
    name: "Plain text link",
    regexp: /(^|\s|\()((http(s?):\/\/)|(www\.))(\w+[^\s\)\<]+)/ig,
    href: function(match) { return "http" + (match[4] ? 's' : '') + '://' + match[5] + match[6]; }
  },
];


/***********************************
 *  Helper functions for filters   *
 ***********************************/

function digits(s)
{
  return s.replace(/[^0-9]/g, "");
}

function alphanumerics(s)
{
  return s.replace(/[^0-9a-z]/ig, "");
}


/***********************************
 *           Link styling          *
 ***********************************/
    
/*

  You can make links generated by AutoLink look different from normal links
  by editing styleLink below and/or by setting up user style sheet rules.
  
  Example: on squarefree.com, make autolinked plain text links orange. (Firefox trunk only.)
  
    @-moz-document domain(squarefree.com) { 
      .autolink-plain-text-link { color: orange ! important; }
    }
      
*/

function styleLink(a, filter)
{
  //a.style.borderBottom = "1px solid orange";
}


/***********************************
 *           Fix filters           *
 ***********************************/

function fixFilters()
{
  var i, r;
  for (i = 0; r = filters[i]; ++i) {
    // lowercase, and replace each run of non-alphanumerics with a single hyphen
    r.classNamePart = r.name.toLowerCase().replace(/[^0-9a-z]+/ig, "-");
    if(!r.regexp.global)
      alert("AutoLink filter " + r.name + " is not global! This will break stuff!");
  }
}
fixFilters();


/***********************************
 *      When and where to run      *
 ***********************************/

var moddingDOM = false;

window.addEventListener("load", init, false);
function init()
{
  document.addEventListener("DOMNodeInserted", nodeInserted, false);
  setTimeout(go, 50, document.body);
}

// This makes it work at Gmail.
// 20% performance penalty on a plain text file with a link on almost every line.
// Tiny performance penalty on pages with few automatically added links.
function nodeInserted(e)
{
  // our own modifications should not trigger this.
  // (we don't want our regular expression objects getting confused)
  // (we want better control over when we recurse)
  
  //GM_log("Inserted: " + e.target);
  
  if (!moddingDOM)
    go(e.target);
}



/***********************************
 *          DOM traversal          *
 ***********************************/


/*

  This script uses manual DOM traversal, in an iterative way without a stack!

  Advantages of snapshot XPath:
    * Much less code
    * 20-40% faster
    * May be possible to get another speed boost by including the regexp in the XPath expression - http://www.developer.com/xml/article.php/10929_3344421_3
    * All the cool people are using it
  
  Advantages of manual DOM traversal:
    * Lets us stop+continue (snapshot xpath doesn't let us)
    * Lets us modify DOM in strange ways without worrying.
    * Easier to control which elements we recurse into.

*/


// Ignore all children of these elements.
const skippedElements = { 
  a:        true, // keeps us from screwing with existing links. keeps us from recursing to death :)
  noscript: true, // noscript has uninterpreted, unshown text children; don't waste time+sanity there.
  head:     true,
  script:   true,
  style:    true,
  textarea: true,
  label:    true,
  select:   true,
  button:   true
}

const gmail = (location.host == "gmail.google.com");

function skipChildren(node)
{
  if (node.tagName)  // !
  {
    if (skippedElements[node.tagName.toLowerCase()]) {
      return true;
    }
    
    if (gmail) {
      if (node.className == "ac") // gmail autocomplete (fake dropdown)
        return true;
      if (node.className == "ilc sxs") // invite foo to gmail (fake link/button)
        return true;
    }
  }

  return false;
}


function go(traversalRoot)
{
  var m;
  
  // Ensure we're not already in a forbidden element.
  for (m = traversalRoot; m != undefined; m = m.parentNode) {
    if (skipChildren(m)) {
      return;
    }
  }

  // work around bug, or in case previous user scripts did crazy stuff
  traversalRoot.normalize();

  function cont(n, didChildren)
  {
    var k = 0; // split work into chunks so Firefox doesn't freeze
    var q;
    
    while (n && k < 100)
    {
      ++k;
    
      // Do stuff at this node
      if (!didChildren && n.nodeType == 3) {
        if((q = runFiltersOnTextNode(n))) {
          n = q[0];

          // if there were changes, run filters again on the new text node that's here          
          if (q[1]) 
            continue;
        }
      }
  
      // Traverse to the "next" node in depth-first order

      if (!n.firstChild)
        didChildren = true;
  
      if (didChildren && n == traversalRoot)
        break;
      else if (!didChildren && n.firstChild && !skipChildren(n)) {
        n = n.firstChild;
        // didChildren is already false and should stay false
      }
      else {
        if (n.nextSibling) {
          n = n.nextSibling;
          didChildren = false;
        }
        else {
          n = n.parentNode;
          didChildren = true;
        }
      }
    } // end while
  
    if (!n) {
      //GM_log("Odd. traversalRoot was " + traversalRoot);
    }
    else if (n == traversalRoot) {
      //GM_log("Done");
      //alert("AutoLink time: " + (new Date() - timeBefore))
    }
    else {
      // Continue after 10ms.
      //GM_log("will have to continue");
      setTimeout(cont, 10, n, didChildren);
    }
    
  } // end function cont
  
  cont(traversalRoot, false);
}


/***********************************
 *         Running filters         *
 ***********************************/

// runFiltersOnTextNode
// Return: node at which to continue traversal, or |null| to mean no changes were made.

function runFiltersOnTextNode(node)
{
  // Too many variables.  Good hint that I need to split this function up :P
  var source, j, regexp, match, lastLastIndex, k, filter, href, anyChanges; // things
  var used, unused, firstUnused, lastUnused, a, parent, nextSibling; // nodes
  
  source = node.data;
  
  anyChanges = false;

  // runFiltersOnTextNode has its own do-too-much-at-once avoider thingie.
  // assumption: if there is one text node with a lot of matches,
  // it's more important to finish quickly than be transparent.
  // (e.g. plain text file FULL of links)
  // assumption: 40 * 100 = 140.
  k=0;
  
  for (j = 0; filter = filters[j]; ++j) {
    regexp = filter.regexp;
    
    if (regexp.test(source)) {

      parent = node.parentNode;
      nextSibling = node.nextSibling;

      
      regexp.lastIndex = 0;
      firstUnused = null;
      
      // Optimization from the linkify that came with Greasemonkey(?):
      // instead of splitting a text node multiple times, take advantage
      // of global regexps and substring.

      for (match = null, lastLastIndex = 0; k < 40 && (match = regexp.exec(source)); ) {
      
        // this should happen first, so RegExp.foo is still good :)
        href = genLink(filter, match); 
        
        if (href != null && href != location.href) { 
          ++k;

          unused = document.createTextNode(source.substring(lastLastIndex, match.index));
          if (!anyChanges) {
            anyChanges = true;
            parent.removeChild(node);
            firstUnused = unused;
            moddingDOM = true;
          }
          parent.insertBefore(unused, nextSibling);

          used = document.createTextNode(match[0])
  
          a = document.createElement("a");
          a.href = href;
          //a.title = "Link added by AutoLink filter: " + filter.name;
          a.className = "autolink autolink-" + filter.classNamePart;
  
          styleLink(a, filter);
  
          a.appendChild(used);
          parent.insertBefore(a, nextSibling);
          
          lastLastIndex = regexp.lastIndex;
        }

      }

      if (anyChanges) {
        lastUnused = document.createTextNode(source.substring(lastLastIndex));
        parent.insertBefore(lastUnused, nextSibling);
        moddingDOM = false;
        return [firstUnused, true]
      }
      
      return [node, false];
    }
  }
  return null;
}

function genLink(filter, match)
{
  try {
    return filter.href(match); 
  }
  catch(er) {
    return "data:text/plain,Error running AutoLink function for filter: " + encodeURIComponent(filter.name) + "%0A%0A" + encodeURIComponent(er);
  }
}

function subscribeToThread(thread_id) {
	var txt = $('#thread_sub').html();
	$('#thread_sub').html('<i>Updating...</i>');
	$.ajax({
		type: 'POST',
		url: '/lib/actions.php',
		data: {action:'subscribeToThread',thread_id:thread_id},
		dataType: 'json',
		success: function(obj) {
			if(obj.success) {
				$('#thread_sub').html('You have successfully subscribed to this topic. <a href="/discussion/options/">View your subscriptions</a>.');
			} else {
				alert(obj.error);
				$('#thread_sub').html(txt);
			}

		}
	});	
}

function unsubscribeToThread(thread_id) {
	var txt = $('#thread_sub').html();
	$('#thread_sub').html('<i>Updating...</i>');
	$.ajax({
		type: 'POST',
		url: '/lib/actions.php',
		data: {action:'unsubscribeToThread',thread_id:thread_id},
		dataType: 'json',
		success: function(obj) {
			if(obj.success) {
				$('#thread_sub').html('You have successfully unsubscribed from this topic.');
			} else {
				alert(obj.error);
				$('#thread_sub').html(txt);
			}

		}
	});	
}

function subscribeToGroup(group_id) {
  var txt = $('#group_sub').html();
  $('#group_sub').html('<i>Updating...</i>');
  $.ajax({
    type: 'POST',
	url: '/lib/actions.php',
	data: {action:'subscribeToGroup',group_id:group_id},
	dataType: 'json',
		success: function(obj) {
			if(obj.success) {
				$('#group_sub').html('You have successfully subscribed to this group.<br/>To cancel your subscription to this group, click <a href="javascript:void(0);" onclick="unsubscribeToGroup('+group_id+');">here</a>.<br/><a href="/discussion/options/">View your subscriptions</a>.');
			} else {
				alert(obj.error);
				$('#group_sub').html(txt);
			}

		}
    });
}

function unsubscribeToGroup(group_id) {
	var txt = $('#group_sub').html();
	$('#group_sub').html('<i>Updating...</i>');
	$.ajax({
		type: 'POST',
		url: '/lib/actions.php',
		data: {action:'unsubscribeToGroup',group_id:group_id},
		dataType: 'json',
		success: function(obj) {
			if(obj.success) {
				$('#group_sub').html('You have successfully unsubscribed from this group.<br/><a href="#" onclick="subscribeToGroup('+group_id+'); return false;"><img src="http://cdn.comixology.com/v2/xtras/icons/icon_watch.png" width="16" height="16" /></a> <a href="#" onclick="subscribeToGroup('+group_id+');return false;">Be notified of new posts to this group</a>.');
			} else {
				alert(obj.error);
				$('#group_sub').html(txt);
			}
		}
	});	
}


