/**
*
* ColumnWrapper
*
* Pseudo-class for chopping up a long text into multiple chunks of even height
* they can be thought of as 'columns' or 'pages' as they're called in the code
*
* loosely based on Randy Simons' Multi Columns @ http://randysimons.com/pagina_129_NL.xhtml
*
*/

// DOM constants--the only nodeTypes we care about.
var ELEMENT_NODE = 1
var TEXT_NODE = 3

var PAGE_MAX_HEIGHT = 600 // corresponds to height of "ul#pagelike li"

var ColumnWrapper = {
  page_type: null,
  offscreen_page: null,
  partial_page: null, // this is a little janky
  num_pages: 0,
  
  /**
  * Slice & dice source HTML into pages
  */
  execute: function(source_id, page_type) {
  	var source_el = $(source_id)
  	var source_node = null
  	var add_node = null
  	
	  this.page_type = page_type
	  if (this.page_type != "full_bleed") $("pagelike").addClass("border") // HACK for TOC
	  
  	this.refresh_offscreen_render_page()
	  
	  // now iterate through the source text, node by node
	  this.add_child_nodes(source_el)
  	
  	this.create_new_page() // just in case anything's sloshing around in there.
  },
  
  /**
  * Iterate through a node's children
  * TODO: make this a recursive call so that we can crack open non-text elements.
  * It will be tricky though because you basically have to divide it in two
  */
  add_child_nodes: function(el) {
    while (source_node = el.firstChild) {
  		if (source_node.nodeType == ELEMENT_NODE) {
  			add_node = source_node.cloneNode(true)
  		} else if (source_node.nodeType == TEXT_NODE) {
  			add_node = document.createTextNode(source_node.nodeValue)
  		}
  		this.add_node_to_offscreen_page(add_node)
  		el.removeChild(source_node)
  	}
  },
  
  /**
  * try to add the node wholesale to the offscreen page. if it doesn't fit, try chopping it up.
  */
  add_node_to_offscreen_page: function(node) {
    this.offscreen_page.grab(node)
	  
  	// if the page can't hold the node we just added, pull it out
  	if (this.offscreen_page_exceeds_max_height()) {
  		this.offscreen_page.removeChild(node)
		  
		  // OK, the whole node didn't fit. if it's a text node, try word by word
		  if (node.nodeType == TEXT_NODE) this.add_words_to_offscreen_page(node)
		  else this.create_new_page(node) // cut our losses & keep moving
		  //this.add_child_nodes(node) // this is where the recursive call should be happening but doesn't work.
  	}
  },
  
  /**
  * like the above add_node_to_offscreen_page, but with finer granularity
  */
  add_words_to_offscreen_page: function(source_text_node) {
    var source_words = source_text_node.nodeValue.split(/\s/)
    var add_words = new Array()
    var add_text_node = document.createTextNode('')
    this.offscreen_page.appendChild(add_text_node)
    
    // now start adding words one-by-one to our new empty text node
    while (source_words.length) {
      add_words.push(source_words.shift())
      add_text_node.nodeValue = add_words.join(' ')
      
      if (this.offscreen_page_exceeds_max_height()) {
        source_words.unshift(add_words.pop()) // remove the camelback-breaking straw!
        add_text_node.nodeValue = add_words.join(' ')
        
        this.create_new_page(document.createTextNode(source_words.join(' ')))
        break
      }
    }
  },
  
  /**
  * once we've filled up our offscreen page, dump its contents into a new page
  * then clean out the offscreen_page and put the overflow from the last page in
  * FIXME: there is still a chance the overflow won't fit in the next page!!!
  * FIXME: what if the offscreen page is empty (in the case of the final call)??
  */
  create_new_page: function(source_overflow_node) {
  	// adjust the DIV to nest in the LI
  	var page_contents = this.offscreen_page.clone(true, true)
  	page_contents.removeClass("offscreenRender")
	  
	  // now make sure that fullpage content gets fit in the appropriate container.
	  // (had not anticipated this in the first draft of this code)
	  if (page_contents.firstChild && (page_contents.firstChild.nodeType == ELEMENT_NODE)
  	  && (page_contents.firstChild.className.match(/fullpage/))) { // hasClass() doesn't work in IE?! ugh.
      page_contents.removeClass("halfColumn").addClass("wholeColumn")
      this.partial_page = null // even if current page is just 1 skinny column, too bad
	  }
	  
  	// now make the LI & append it.
  	if (!this.partial_page) { // if no partial LI is open, we make a new one
  	  this.num_pages++
  	  
  	  var new_page = document.createElement('li')
    	new_page.id = "page" + this.num_pages
    	new_page.appendChild(page_contents)
    	$("pagelike").appendChild(new_page)
    	
    	if (this.offscreen_page.hasClass("halfColumn")) this.partial_page = new_page
  	} else { // there's already a partial open; add to it, don't make a new one
  	  this.partial_page.appendChild(page_contents)
  	  this.partial_page = null // and close it out
  	}
  	
  	// now clean out the offscreen page
  	this.refresh_offscreen_render_page(source_overflow_node)
  },
  
  /**
  * init offscreen render pane. see CSS for these classes.
  * not sure if it's wasteful to create & re-create pages
  */
  refresh_offscreen_render_page: function(source_overflow_node)
  {
    // NOTE: offscreenRenderHolster MAY be null here in IE if content is malformed
    if (this.offscreen_page) $("offscreenRenderHolster").removeChild(this.offscreen_page)
    
    // determine page type to use. default is "whole_then_half"
    var num_columns_class = "halfColumn"
    if (this.page_type == "whole_then_half" && this.num_pages == 0) num_columns_class = "wholeColumn"
    else if (this.page_type == "full_bleed") num_columns_class = "fullBleedColumn"
        
    this.offscreen_page = new Element('div', {
  		'class': "offscreenRender " + num_columns_class
  	})
  	$("offscreenRenderHolster").appendChild(this.offscreen_page) // has to be in the DOM
  	
  	//this.offscreen_page.empty()
		if (source_overflow_node) this.offscreen_page.appendChild(source_overflow_node)
  },
  
  offscreen_page_exceeds_max_height: function() {
    return (this.offscreen_page.getSize().y > PAGE_MAX_HEIGHT)
  }
}
