/**
 * Topic functionality.
 * @author Aaron Collegeman aaroncollegeman@gmail.com
 */
(function() {
  var i = setInterval(function() {

    if (window.jQuery) {
      clearInterval(i);
    } else {
      return;
    }
    
    (function($) {
  
      var lookup = {};
      var pickers = {};
      var other = /^(Other|More)$/i;
      var other_ = /^(Other|More) +/i;
      
      var btn_done_visible = '<span class="cat_complete" title="Lens topics updates">Done</span>';
      var btn_done = '<span class="cat_complete" title="Lens topics updates" style="display:none;">Done</span>';
      var btn_ok = '<a class="cat_click" title="Click to update" href="#" onclick="Topics.updateLens(this); return false;">OK</a>';
      var btn_ok_disabled = '<span class="cat_disable" title="Update your topics first">OK</span>';
      var btn_wait = '<img class="cat_wait" src="/imgs/loading_like.gif" />';
      
      var self = window.Topics = {
        
        has_more_fresh_lenses: true,
        has_more_top_performers: true,
        
        toggleAutoScroll: function() {},
    
        scrollLensList: function(list, dir, topic_id, button) {
          list = $('#'+list);
          
          // setup the limit?
          if (!list.data('setup')) {
            // fix the size of the parent div
            var con = list.parent();
            con.css('height', list.height()+'px').css('overflow', 'hidden');
            list.css('position', 'relative');
            list.data('setup', true).data('pos', 0);
            list.data('limit', list.find('li').size());
          }
        
          if (dir == 'up') {
            if (list.data('pos') > 0) {
              var prev_iter = list.data('pos') - list.data('limit');
              var scroll_to = Math.max(prev_iter, 0);
              list.animate({ top: -1 * list.find('li:eq('+scroll_to+')').position().top });
              list.data('pos', scroll_to);
              if (list.data('pos') == 0) {
                $(button).attr('class', '').addClass('vert_scroll_up_off');
              }
              if (list.find('li').size() > list.data('limit')) {
                $(button).siblings('.vert_scroll_down, .vert_scroll_down_off').attr('class', '').addClass('vert_scroll_down');
              }
            }
            
          } else if (dir == 'down') {
            var has_more_prop = 'has_more_'+list.attr('id');
            var was_size = list.find('li').size();
            if (self[has_more_prop] && list.data('pos') >= was_size-list.data('limit')) {
              
              var pause = $(button).parent().siblings('.topic_pause_spin, .topic_pause');
              pause.show();
              
              $.get('/topics/more_'+list.attr('id')+'/'+topic_id, { offset: was_size, limit: list.data('limit') }, function(html) {
                // get the latest stuff
                list.append(html);
                // do we have more
                if (list.find('li').size() > was_size) {
                  // scroll up!
                  list.animate({ top: -1 * list.find('li:eq('+was_size+')').position().top });
                  list.data('pos', was_size);
                }
                // are there more to load? if not, change button state
                if (!self[has_more_prop]) {
                  $(button).attr('class', '').addClass('vert_scroll_down_off');
                }
                if (list.data('pos') > 0) {
                  $(button).siblings('.vert_scroll_up, .vert_scroll_up_off').attr('class', '').addClass('vert_scroll_up');
                }
                
                pause.hide();
              });
            } else {
              if (list.data('pos') < list.find('li').size()-1) {
                var next_iter = list.data('pos') + list.data('limit');
                var last = list.find('li').size() - 1;
                var scroll_to = Math.min(next_iter, last);
                list.animate({ top: -1 * list.find('li:eq('+scroll_to+')').position().top });
                list.data('pos', scroll_to);
                if (scroll_to == last) {
                  $(button).attr('class', '').addClass('vert_scroll_down_off');
                }
                $(button).siblings('.vert_scroll_up, .vert_scroll_up_off').attr('class', '').addClass('vert_scroll_up');
              }
            }
          }
        },
    
        updateLens: function(a) {
          var tr = $(a).parent().parent();
          
          if (!parseInt(tr.find('.topic_id2 select').val())) {
            if (!confirm("Are you sure you don't want to put this lens in a subtopic? It's great for the findability of your lenses.")) {
              return;
            }
          }

          $(a).parent().html(btn_wait);
  
          $.post('/utility/recategorize_lens/'+tr.attr('rel'), tr.find('select').serialize(), function(result) {
            if (result) {
              alert(result);
              tr.find('.button').html(btn_ok);
            } else {
              tr.find('.button').html(btn_done);
              tr.find('.cat_complete').fadeIn();
            }
          });
        },
    
        /**
         * Bulk categorization tool.
         * @param string lm (optional) alternatively, load lenses by some other lensmaster
         */
        initBulkCatTool: function(lm) {
          var tbody = $('.bulk-cat .tool table tbody');
          var model = $('.bulk-cat table.model tr');

          // load the top level topics
          self.getList('__top__', function(top_level_topics) {
            // load the list of lenses to be categorized
            $.getJSON('/lensmaster/lenses_to_categorize', { lm: lm }, function(lenses) {
              // loop over the lens list
              $.each(lenses, function(i, lens) {
                // create a new row for the table
                model.clone().appendTo(tbody);
                // tag the new row with the lens' id and name
                var tr = tbody.find('tr:last');
                tr.attr('id', 'lens_'+lens.id);
                tr.attr('rel', lens.n);
                
                // truncate the lens title, add elipsis if necessary, and setup the link to the lens
                var t = lens.t.substring(0, 18);
                if (t != lens.t) {
                  t += '...';
                }
                var title = tbody.find('tr:last .title a');
                title.text(t);
                title.attr('href', 'http://www.squidoo.com/'+lens.n);
                title.attr('title', lens.t);
              
                // setup topic1 picker, with top level topics
                var topic_id1 = tbody.find('tr:last .topic_id1');
                var select1 = topic_id1.find('select');
                select1.attr('id', 'lens_'+lens.id+'_topic_id1');
                $.each(top_level_topics, function(n, topic) {
                  select1.append('<option value="'+topic.v+'">'+topic.l+'</option>');
                });  
              
                // setup topic2 picker
                var topic_id2 = tbody.find('tr:last .topic_id2');
                var select2 = topic_id2.find('select'); 
                select2.data('needs_refresh', true);
                select2.data('parent', select1);
                select2.attr('id', 'lens_'+lens.id+'_topic_id2');
                if (lens.t1) {
                  select2.attr('disabled', false);
                  if (parseInt(lens.tid2)) {
                    select2.append('<option value="'+lens.tid2+'">'+lens.t2+'</option>').val(lens.tid2);
                  } else {
                    select2.append('<option value="">Choose a subtopic</option>');
                  }
                }
              
                // setup topic3 picker
                var topic_id3 = tbody.find('tr:last .topic_id3');
                var select3 = topic_id3.find('select');
                select3.data('needs_refresh', true);
                select3.data('parent', select2);
                select3.attr('id', 'lens_'+lens.id+'_topic_id3');
                if (lens.t2) {
                  select3.attr('disabled', false);
                  if (parseInt(lens.tid3)) {
                    select3.append('<option value="'+lens.tid3+'">'+lens.t3+'</option>').val(lens.tid3);
                  }
                }
                
                (function(selects) {
                  $.each(selects, function(i, select) {
                    var handler = function() {
                      if (select.data('needs_refresh')) {
                        var parent = select.data('parent');
                        if (parent.val()) {
                          select.data('temp_val', select.val());
                          self.getList(parent.val(), function(list) {
                            select.html('<option value="">'+select.attr('title')+'</option>');
                            $.each(list, function(i, topic) {
                              select.append('<option value="' + topic.v + '">' + topic.l + '</option>');
                            });
                            select.val(select.data('temp_val'));
                            select.data('temp_val', null); 
                          });
                          select.data('needs_refresh', false);
                        }
                      }
                    };
                    
                    select.bind('focus', handler);
                    select.bind('mouseenter', handler);
                  });
                })([select2, select3]);
              
                // setup picker change events
                self.onChange('lens_'+lens.id+'_topic_id1', 'lens_'+lens.id+'_topic_id2', null);
                self.onChange('lens_'+lens.id+'_topic_id2', 'lens_'+lens.id+'_topic_id3', null);
                self.onChange('lens_'+lens.id+'_topic_id3', null, null);
                
                if (parseInt(lens.tid1)) {
                  select1.val(lens.tid1);
                }
                
                select2.bind('selected', function() {
                  tr.find('.button').html(btn_ok);
                }).bind('cleared', function() {
                  tr.find('.button').html(btn_ok);
                });
                
                select3.bind('selected', function() {
                  tr.find('.button').html(btn_ok);
                }).bind('cleared', function() {
                  tr.find('.button').html(btn_ok);
                });
                
                // when pickers are used, update tablesorter parser cache
                var cache_update_delay = null;
                $.each([ select1, select2, select3 ], function(p, picker) {
                  picker.bind('selected', function(event, topic) {
                    clearTimeout(cache_update_delay);
                    cache_update_delay = setTimeout(function() {
                      $('.bulk-cat .tool table').trigger('update');
                    }, 5000);
                  }).focus(function() {
                    $(this).addClass('withfocus');
                  }).blur(function() {
                    $(this).removeClass('withfocus');
                  });
                });
                
                select1.change(function() {
                  if (select1.val()) {
                    button.html(btn_ok);
                  } else {
                    button.html(btn_ok_disabled);
                  }
                });
                
                var button = tbody.find('tr:last .button');
                if (lens.dn) { // "done"
                  button.html(btn_done_visible);
                } else if (select1.val()) {
                  button.html(btn_ok);
                } else {
                  button.html(btn_ok_disabled);
                }
              });
            
              $.tablesorter.addParser({
                id: 'topic_picker',
                is: function(s) {
                  return false; // do not autodetect
                },
                format: function(s, table, cell) {
                  var selected = $(cell).find('select option:selected');
                  return selected.text();
                },
                type: 'text'
              });
              
              $.tablesorter.addParser({
                id: 'topic_btn',
                is: function(s) {
                  return false;
                },
                format: function(s, table, cell) {
                  var val = 0;
                  if ($(cell).find('.cat_disable').size()) {
                    val = 1;
                  } else if ($(cell).find('.cat_click').size()) {
                    val = 2;
                  } else if ($(cell).find('.cat_complete').size()) {
                    val = 3;
                  }
                  return val;
                },
                type: 'numeric'
              });
            
              $('.bulk-cat .tool table').tablesorter({
          			widgets: ['zebra'],
                debug: false,
                headers: {
                  0: { sorter: 'title' },
                  1: { sorter: 'topic_picker' },
                  2: { sorter: 'topic_picker' },
                  3: { sorter: 'topic_picker' },
                  4: { sorter: 'topic_btn' }
                }
          		});
            
              $('.bulk-cat .wait').hide();
              $('.bulk-cat .tool').show();
            });
          });
        },
    
        /**
         * connect to the back-end and grap the Topics
         * @param parent_id The parent Topic id (optional)
         * @param do_with_list A callback function to fire with the unencoded list
         */
        getList: function(parent_id, do_with_list) {
          if (!parent_id) {
            parent_id = '__top__';
          }
      
          if (!lookup[parent_id]) {
            $.get('/topics/json/'+parent_id, function(json) {
              var list = eval('('+json+')');
              
              // sort "Other" and "Other ..." to the bottom of the list
              var top = [];
              var bottom = [];
              $.each(list, function(i, t) {
                if (t.l.match(other) || t.l.match(other_)) {
                  bottom.push(t);
                } else {
                  top.push(t);
                }
              });
              
              lookup[parent_id] = list = top.concat(bottom);
              do_with_list(list);
            })
          } else {
            do_with_list(lookup[parent_id]);
          }
        },
    
        /**
         * An onChange event handler for topic pickers
         * @param select_id The element ID of the <select> element
         * @param child_select_id (optional) The element ID of the <select> element that will show children of the Topic picked from select_id
         * @param child_con_id (optional) The element ID of the container for child_select_id, if one should be hidden/revealed as child_select_id becomes available
         */
        onChange: function(select_id, child_select_id, child_con_id) {

          // first, catalog the picker, so that we can reverse actions
          var picker = pickers[select_id] = { 
            me: $('#'+select_id), 
            child_con_id: child_con_id,
            child_con: child_con_id ? $('#'+child_con_id) : null,
            child_select_id: child_select_id, 
            child: child_select_id ? $('#'+child_select_id) : null
          };
          
          picker.me.change(function() {
            // first, reset children
            self.resetChildren(select_id);
            
            // next, load my child with values
            if (picker.me.val() && picker.child) {
              $('.topics_update_wait').show();
              self.getList(picker.me.val(), function(list) {
                $('.topics_update_wait').hide();
                if (!list.length) {
                  picker.child.html('<option value="">No subtopics</option>');
                  return;
                }
            
                if (picker.child_select_id) {
                  picker.child.html('<option value="">'+picker.child.attr('title')+'</option>');
                  $.each(list, function(i, item) {
                    picker.child.append('<option value="'+item.v+'">'+item.l+'</option>');
                  });
                  
                  // did the picker already have a selected val? return to it
                  if (picker.child.data('temp_val')) {
                    picker.child.val(picker.child.data('temp_val'));
                    picker.child.data('temp_val', null);
                  }

                  picker.child.data('needs_refresh', false);
                  
                  // last, reveal the child, if it isn't already
                  picker.child.attr('disabled', false).show();
                  if (picker.child_con_id) {
                    picker.child_con.fadeIn('fast');
                  }
                }
              });
              
              picker.me.trigger('selected', [ { topic_id: picker.me.val(), topic_title: picker.me.find(':selected').text() } ]);
            } else {
              picker.me.trigger('cleared', [ { topic_id: null, topic_title: null } ]);
            }
          });
        },
    
        /**
         * Reset picker's children, recursively.
         */
        resetChildren: function(select_id) {
          if (select_id) {
            var picker = pickers[select_id];
            if (picker.child_select_id) {
              picker.child.data('temp_val', picker.child.val());
              picker.child.attr('disabled', true).html('<option>Please pick a parent</option>');
              self.resetChildren(picker.child_select_id);
              if (picker.child_con_id) {
                picker.child_con.hide();
              }
            }
          }
        }
      };
    })(jQuery);
  
  }, 500);
  
})();
