(function($) {

  /**
   * This adds a Chosen style selector for the tree select widget.
   *
   * This widget requires chosen.css.
   */
  $.fn.chosentree = function(params) {

    // Setup the default parameters.
    params = $.extend({
      inputId: 'chosentree-select',     /** The input element ID and NAME. */
      label: '',                        /** The label to add to the input. */
      description: '',                  /** The description for the input. */
      input_placeholder: null, /** The input placeholder text. */
      input_type: 'text',               /** Define the input type. */
      autosearch: false,                /** If we would like to autosearch. */
      search_text: 'Search',            /** The search button text. */
      no_results_text: 'No results found', /** Shown when no results. */
      min_height: 100,                  /** The miniumum height. */
      more_text: '+%num% more',         /** The text to show in the more. */
      loaded: null,                     /** Called when all items are loaded. */
      collapsed: true,                  /** If the tree should be collapsed. */
      showtree: false,                   /** To show the tree. */
      inputName:'treeselect'
    }, params);

    // Iterate through each instance.
    return $(this).each(function() {

      // Keep track of the treeselect.
      var selector = null;
      var choices = null;
      var search = null;
      var input = null;
      var search_btn = null;
      var label = null;
      var description = null;
      var treeselect = null;
      var treewrapper = null;
      var selectedTimer = 0;
      var root = null;

      // Show or hide the tree.
      var showTree = function(show, tween) {
        tween = tween || 'fast';
        if (show && (!root || root.has_children)) {
          treewrapper.addClass('treevisible').show('fast');
        }
        else {
          treewrapper.removeClass('treevisible').hide('fast');
        }
      };

      if ($(this).find(".chzntree-container").length == 0) {

          // Create the selector element.
          selector = $(document.createElement('div'));
          selector.addClass('chzntree-container');
          selector.addClass('chzntree-container-multi');
          choices = $(document.createElement('ul'));
          choices.addClass('chzntree-choices chosentree-choices');

          // If they wish to have a label.
          label = $(document.createElement('label'));
          label.attr({
              'for': params.inputId
          });
          label.text(params.label);

          // If they wish to have a description.
          description = $(document.createElement('div'));
          description.attr({
              'class': 'description'
          });
          description.text(params.description);

          // Creat the chosen selector.
          if (choices) {
              selector.append(label).append(choices.append(search));
          }
          else {
              selector.append(label).append(search);
          }

          // Add the description.
          $(this).append(description);
      }
      else {
          treeselect = $(this).find('.treeselect');
          treewrapper = $(this).find('.treewrapper');
          selector = $(this).find('.chzntree-container');
          treeselect.remove();
          treewrapper.remove();;
      }

      treewrapper = $(document.createElement('div'));
      treewrapper.addClass('treewrapper');
      treewrapper.hide();

        // Get the tree select.
      treeselect = $(document.createElement('div'));
      treeselect.addClass('treeselect');

        // Setup the keyevents.
      $(this).keyup(function (event) {
          if (event.which == 27) {
              showTree(false);
          }
      });

        // Add the treeselect widget.
      treewrapper.append(treeselect);
      $(this).append(selector.append(treewrapper));

      // Now declare the treeselect.
      var treeparams = params;

      // Now declare our treeselect control.
      treeselect.treeselect(treeparams);
      root = treeselect.eq(0)[0].treenode;

      // Show the tree by default.
      if (treeparams.showtree || !treeparams.collapsed) {
        showTree(true, null);
      }

      treeparams.selected = (function (chosentree) {
          if (treeparams.loaded) {
              treeparams.loaded();
          }
          $(chosentree).trigger('treeloaded');
      })(this);
    });
  };
})(jQuery);
