// ----------------------------------
// Back buttons and sliders
// ----------------------------------
$('thread_back').observe('click', function(event) {
  slideAndShowForums();
});

function slideAndShowForums() {
  $('forums_container').morph('left: 40px', {duration: 0.5});
  $('threads_container').morph('left: 795px', {duration: 0.5});
  $('posts_container').morph('left: 1590px', {duration: 0.5});
  loadForums();
}

function slideAndShowThreads() {
  $('forums_container').morph('left: -755px', {duration: 0.5});
  $('threads_container').morph('left: 40px', {duration: 0.5});
  $('thread_new_container').morph('left: 795px', {duration: 0.5});
  $('posts_container').morph('left: 795px', {duration: 0.5});
}

function slideAndShowNewThread() {
  $('forums_container').morph('left: -1550px', {duration: 0.5});
  $('threads_container').morph('left: -755px', {duration: 0.5});
  $('thread_new_container').morph('left: 40px', {duration: 0.5});
}

function slideAndShowPosts() {
  $('forums_container').morph('left: -1550px', {duration: 0.5});
  $('threads_container').morph('left: -755px', {duration: 0.5});
  $('posts_container').morph('left: 40px', {duration: 0.5});
  $('post_edit_container').morph('left: 795px', {duration: 0.5});
}

function slideAndShowPostEdit() {
  $('posts_container').morph('left: -755px', {duration: 0.5});
  $('post_edit_container').morph('left: 40px', {duration: 0.5});
}


// ----------------------------------
// Forums
// ----------------------------------
function loadForums() {
  spinnerShow('forums_indeterminate');
  $$('#forums_container tr.none').invoke('hide');
  ajaxWrapper('api/forums/', {course: courseID}, function(json) { return json.general && json.questions; }, loadForumsSuccessful, loadForumsFailure);
}

function loadForumsSuccessful(json) {
  drawForums('forums_general', json.general);
  drawForums('forums_questions', json.questions);
  spinnerHide('forums_indeterminate');
}

function loadForumsFailure(transport, reason) {
  alert(reason || "An error occurred while loading the forums. The server may be experiencing problems. Please log out, and try using the challenge again in a few minutes.");
  spinnerHide('forums_indeterminate');
}

// UI
var FORUMS_TEMPLATE = new Template("<td class='description'><div class='name'>#{unread_str}#{name}</div><div class='meta'>#{description}</div></td><td class='count'>#{nthreads}</td>");
function drawForums(id, forums) {
  var table = $$('#' + id + ' tbody').first();
  table.update();
 
  if (forums.size() == 0) {
    $$('#' + id + ' tr.none').first().show();
    return;
  }

  forums.each(function(forum) {
    tr = new Element('tr');
    table.appendChild(tr);
    if (forum.has_unread)
      forum.unread_str = '<img src="/images/unread.png" alt=""> ';
    tr.insert(FORUMS_TEMPLATE.evaluate(forum));
    tr.observe('click', function(event) {
      loadThreads(forum);
    });
  });
}

// ----------------------------------
// Threads
// ----------------------------------
function loadThreads(forum) {
  // set up the UI before sliding
  spinnerShow('threads_indeterminate');
  $('threads_heading').innerHTML = forum.name;
  
  // request the threads
  ajaxWrapper('/api/forums/threads/', {course: courseID, forum: forum.id}, function(json) { return json.threads && json.forum; }, loadThreadsSuccessful, loadThreadsFailure);
  slideAndShowThreads();
}

function loadThreadsSuccessful(json) {
  drawThreads(json.forum, json.threads);
  if (json.can_start)
    $('thread_new_button').show();
  else
    $('thread_new_button').hide();
  spinnerHide('threads_indeterminate');
}

function loadThreadsFailure(transport, msg) {
  alert(msg || "An error occurred while loading the threads for this forum. The server may be experiencing problems. Please log out, and try using the challenge again in a few minutes.");
  spinnerHide('threads_indeterminate');
}

var THREADS_TEMPLATE = new Template("<td class='description'><div class='name'>#{unread_str}#{title}</div><div class='meta'><span class='name'>#{author}</span>, #{timestamp}</div></td><td class='count'>#{nposts}</td>");
function drawThreads(forum, threads) {
  var table = $$('#threads_list tbody').first();
  table.update();

  var add = $('thread_new_button');
  add.stopObserving('click');
  add.observe('click', function(event) {
    showNewThread(forum);
  });

  if (threads.size() == 0) {
    tr = new Element('tr');
    table.appendChild(tr);
    tr.insert("<td colspan='2'>No threads found</td>");
    return;
  }
  threads.each(function(thread) {
    tr = new Element('tr');
    table.appendChild(tr);
    if (thread.has_unread)
      thread.unread_str = '<img src="/images/unread.png" alt=""> ';
    tr.insert(THREADS_TEMPLATE.evaluate(thread));
    tr.observe('click', function(event) {
      loadPosts(forum, thread);
    });
  });
}


// ----------------------------------
// New Thread
// ----------------------------------
function leaveNewThread(forum) {
  $('thread_new_title').disabled = true;
  $('thread_new_content').disabled = true;
  $('thread_new_preview').disabled = true;
  $('thread_new_create').disabled = true;
  loadThreads(forum);
}

function showNewThread(forum) {
  spinnerShow('thread_new_indeterminate');
  slideAndShowNewThread();
  var title = $('thread_new_title');
  title.disabled = false;
  title.value = '';

  var content = $('thread_new_content');
  content.disabled = false;
  content.value = '';
  
  var back = $('thread_new_back');
  back.stopObserving('click');
  back.observe('click', function(event) {
    leaveNewThread(forum);
  });
  
  var preview = $('thread_new_preview');
  preview.disabled = false;
  preview.stopObserving('click');
  preview.observe('click', function(event) {
    newThreadPreview();
  });
  
  var create = $('thread_new_create');
  create.disabled = true;
  create.stopObserving('click');
  create.observe('click', function(event) {
    newThreadCreate(forum);
  });

  $('thread_new_msg').update();
  $('thread_new_content_preview').update();

  spinnerHide('thread_new_indeterminate');
}


function newThreadPreview() {
  spinnerShow('thread_new_indeterminate');
  $('thread_new_create').disabled = true;
  $('thread_new_content_preview').update();
  msgDivClear('thread_new_msg');
  ajaxWrapper('api/forums/render_markup', {content: $('thread_new_content').value}, function(json) { return json.html; }, newThreadPreviewSuccess, newThreadPreviewFailure);
}

function newThreadPreviewSuccess(json) {
  var container = $('thread_new_content_preview');
  container.update();
  container.innerHTML = json.html;
  MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'thread_new_content_preview']);

  $('thread_new_create').disabled = false;
  spinnerHide('thread_new_indeterminate');
}

function newThreadPreviewFailure(transport, msg) {
  msgDivDisplay('thread_new_msg', msg || "An error occured", false);
  spinnerHide('thread_new_indeterminate');
}

function newThreadCreate(forum) {
  spinnerShow('thread_new_indeterminate');
  $('thread_new_content_preview').update();
  msgDivClear('thread_new_msg');
  ajaxWrapper('api/forums/threads/create', {course: courseID, forum: forum.id, title: $('thread_new_title').value, content: $('thread_new_content').value}, function(json) { return json.forum; }, newThreadCreateSuccess, newThreadCreateFailure);
}

function newThreadCreateSuccess(json) {
  spinnerHide('thread_new_indeterminate');
  leaveNewThread(json.forum);
}

function newThreadCreateFailure(transport, msg) {
  msgDivDisplay('thread_new_msg', msg || 'An error occured while trying to create your thread', false);
  spinnerHide('thread_new_indeterminate');
}



// ----------------------------------
// Posts
// ----------------------------------
function leavePosts(forum) {
  loadThreads(forum);
}

function loadPosts(forum, thread) {
  spinnerShow('posts_indeterminate');
  $('posts_heading').innerHTML = thread.title;
  $('posts_list').update();
  $('posts_back').stopObserving('click');
  $('posts_back').observe('click', function(event) {
    leavePosts(forum);
  });
  ajaxWrapper('api/forums/posts/', {course: courseID, thread: thread.id}, function(json) { return json.posts; }, loadPostsSuccess.curry(forum), loadPostsFailure);
  slideAndShowPosts();
}

function loadPostsSuccess(forum, json) {
  drawPosts(forum, json.thread, json.posts);
  if (json.can_start)
    $('posts_new_post').show();
  else
    $('posts_new_post').hide();
  spinnerHide('posts_indeterminate');
}

function loadPostsFailure(transport, msg) {
  alert(msg || "An error occurred while loading the posts for this thread. The server may be experiencing problems. Please log out, and try using the challenge again in a few minutes.");
  spinnerHide('posts_indeterminate');
}


var POSTS_TEMPLATE = new Template("<div class='post post#{depth}' id='post_#{id}'><div class='post_content confluence'>#{html}</div><div class='meta'><span id='post_liked_container_#{id}'><img src='images/thumbs-up.png' alt=''> <span id='post_liked_#{id}'>#{nliked}</span> </span>#{user_footer}<span class='actions'><span id='post_like_#{id}' class='action'>Like</span> <span id='post_reply_#{id}' class='action'>Reply</span> <span id='post_edit_#{id}' class='action'>Edit</span> <span id='post_delete_#{id}' class='action'>Delete</span></span></div></div>");
function drawPosts(forum, thread, posts) {
  var container = $('posts_list');
  container.update();
  
  var button = $('posts_new_post');
  button.stopObserving('click');
  button.observe('click', function(event) {
    showPostEdit(forum, thread, null, null);
  });

  function toggleAction(prefix, post, enable, fn) {
    var action = $(prefix + post.id);
    if (enable) {
      action.stopObserving('click');
      action.observe('click', function(event) {
        fn();
      });
      action.show();
    }
    else
      action.hide();
  }

  function _drawPosts(_posts, depth) {
    _posts.each(function(post) {
      post.depth = depth;
      post.user_footer = userFooter(post);
      container.innerHTML += POSTS_TEMPLATE.evaluate(post);
      MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'post_' + post.id]);
      _drawPosts(post.children, depth + 1);
    });
  }
  
  function _toggleActions(_posts, depth) {
    _posts.each(function(post) {
      if (post.nliked)
        $('post_liked_container_' + post.id).show();
      else
        $('post_liked_container_' + post.id).hide();
      toggleAction('post_like_', post, post.can_like, doPostLike.curry(forum, thread, post));
      toggleAction('post_reply_', post, post.can_reply, showPostEdit.curry(forum, thread, null, post));
      toggleAction('post_edit_' , post, post.can_edit , showPostEdit.curry(forum, thread, post, null));
      toggleAction('post_delete_', post, post.can_delete, showPostDelete.curry(forum, thread, post));
      _toggleActions(post.children, depth + 1);
    });
  }

  _drawPosts(posts, 0);
  _toggleActions(posts, 0);
}


function showPostDelete(forum, thread, post) {
  if (confirm('Are you sure you wish to delete the post?')) {
    spinnerShow('posts_indeterminate');
    ajaxWrapper('api/forums/posts/delete', {course: courseID, thread: thread.id, post: post.id}, null, showPostDeleteSuccess.curry(forum, thread), showPostDeleteFailure);
  }
}

function showPostDeleteSuccess(forum, thread, json) {
  spinnerHide('posts_indeterminate');
  ajaxWrapper('api/forums/posts/', {course: courseID, thread: thread.id}, function(json) { return json.posts; }, loadPostsSuccess.curry(forum), loadPostsFailure);
}

function showPostDeleteFailure(transport, msg) {
  alert(msg || 'An error occurred while trying to delete the post');
  spinnerHide('posts_indeterminate');
}



function doPostLike(forum, thread, post) {
  spinnerShow('posts_indeterminate');
  ajaxWrapper('api/forums/posts/like', {course: courseID, thread: thread.id, post: post.id}, null, doPostLikeSuccess.curry(forum, thread, post), doPostLikeFailure);
}

function doPostLikeSuccess(forum, thread, post, json) {
  $('post_liked_' + post.id).innerHTML = json.nliked;
  $('post_liked_container_' + post.id).show();
  $('post_like_' + post.id).hide();
  spinnerHide('posts_indeterminate');
}

function doPostLikeFailure(transport, msg) {
  alert(msg || 'An error occurred while trying to delete the post');
  spinnerHide('posts_indeterminate');
}


// ------
// Post Edit
// ------
function leavePostEdit(forum, thread) {
  $('post_edit_content').disabled = true;
  $('post_edit_preview').disabled = true;
  $('post_edit_create').disabled = true;
  $('post_edit_reply').hide();
  loadPosts(forum, thread);
}

function showPostEdit(forum, thread, post, parentPost) {
  spinnerShow('post_edit_indeterminate');
  $('post_edit_heading').innerHTML = post ? 'Edit Post' : (parentPost ? 'Reply to Post' : 'Create Post');

  var back = $('post_edit_back');
  back.stopObserving('click');
  back.observe('click', function(event) {
    leavePostEdit(forum, thread);
  });

  var content = $('post_edit_content');
  content.disabled = false;
  content.value = post ? post.content : '';

  var preview = $('post_edit_preview');
  preview.disabled = false;
  preview.stopObserving('click');
  preview.observe('click', function(event) {
    postEditPreview(thread, post, parentPost);
  });

  var create = $('post_edit_create');
  create.value = post ? 'Save' : 'Create';
  create.stopObserving('click');
  create.observe('click', function(event) {
    if (post)
      doPostEdit(forum, thread, post);
    else
      doPostCreate(forum, thread, parentPost);
  });
  
  if (parentPost) {
    var _post = Object.clone(parentPost);
    _post.depth = 1;
    _post.id = _post.id + '_fake';
    $('post_edit_reply_content').update();
    $('post_edit_reply_content').innerHTML = POSTS_TEMPLATE.evaluate(_post);
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'post_edit_reply_content']);
    $('post_liked_container_'  + _post.id).hide();
    $('post_like_'  + _post.id).hide();
    $('post_reply_'  + _post.id).hide();
    $('post_edit_'   + _post.id).hide();
    $('post_delete_' + _post.id).hide();
    $('post_edit_reply').show();
  }
  
  msgDivClear('post_edit_msg');
  $('post_edit_content_preview').update();

  slideAndShowPostEdit();
  spinnerHide('post_edit_indeterminate');
}

function postEditPreview() {
  spinnerShow('post_edit_indeterminate');
  $('post_edit_create').disabled = true;
  $('post_edit_content_preview').update();
  msgDivClear('post_edit_msg');
  ajaxWrapper('api/forums/render_markup', {content: $('post_edit_content').value}, function(json) { return json.html; }, postEditPreviewSuccess, postEditPreviewFailure);
}

function postEditPreviewSuccess(json) {
  $('post_edit_content_preview').innerHTML = '<h2>Preview</h2>\n' + json.html;
  MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'post_edit_content_preview']);
  $('post_edit_create').disabled = false;
  spinnerHide('post_edit_indeterminate');
}

function postEditPreviewFailure(transport, msg) {
  msgDivDisplay('post_edit_msg', msg || 'An error occured while trying to generate a preview', false);
  spinnerHide('post_edit_indeterminate');
}

function doPostEdit(forum, thread, post) {
  spinnerShow('post_edit_indeterminate');
  $('post_edit_create').disabled = true;
  msgDivClear('post_edit_msg');
  ajaxWrapper('api/forums/posts/edit', {course: courseID, thread: thread.id, post: post.id, content: $('post_edit_content').value}, null, doPostEditSuccess.curry(forum, thread), doPostEditFailure);
}

function doPostEditSuccess(forum, thread, json) {
  spinnerHide('post_edit_indeterminate');
  leavePostEdit(forum, thread);
}

function doPostEditFailure(transport, msg) {
  msgDivDisplay('post_edit_msg', msg || 'An error occured while trying to save your changes', false);
  spinnerHide('post_edit_indeterminate');
}

function doPostCreate(forum, thread, parentPost) {
  spinnerShow('post_edit_indeterminate');
  $('post_edit_create').disabled = true;
  msgDivClear('post_edit_msg');
  var data = {course: courseID, thread: thread.id, content: $('post_edit_content').value};
  if (parentPost)
    data['parent'] = parentPost.id;
  ajaxWrapper('api/forums/posts/create', data, null, doPostCreateSuccess.curry(forum, thread), doPostCreateFailure);
}

function doPostCreateSuccess(forum, thread, json) {
  spinnerHide('post_edit_indeterminate');
  leavePostEdit(forum, thread);
}

function doPostCreateFailure(transport, msg) {
  msgDivDisplay('post_edit_msg', msg || 'An error occured while trying to create your post', false);
  spinnerHide('post_edit_indeterminate');
}

