// Extend the initial PGPW object instead of replacing or redefining it
JQ.extend(PGPW,{

  ////////////////////////////
  // Dynamic node insertion //
  ////////////////////////////
  insertNumber:Math.floor(Math.random()*1000000),

  // Call a url and add the widget's options if an instance is passed
  callScript:function(url,instance){
    var full_url = url

    if (instance){
      var Widget = PGPW.getWidgetObject(instance)
      // If we have stuff to append to the query string, we need to make
      // sure there is a "?".
      full_url += ((instance)?((url.match(/\?/))?'':'?pgpw=1'):'')
      full_url += '&item='+escape(PGPW.getInstanceWordyId(instance))
      full_url += '&html_id='+escape(PGPW.getInstanceHTMLId(instance))
      full_url += '&options='+escape(JQ.toJSON(Widget.Instances[PGPW.getInstanceHTMLId(instance)].Options))
    }

    PGPW.insertScript(full_url)
  },
  insertScript:function(url){
    var script = document.createElement('script')
    // Yeah, Safari will cache scripts and NOT call them again!
    // I'm using the Rails technique of appending a random number
    // to keep them from being cached. jQuery and PGPW are still
    // cached since they are loaded by the initial PGPW object's
    // insertScript(). Sheesh!
    script.src = url+((url.match(/\?/)) ? '&':'?')+PGPW.insertNumber
    script.type = 'text/javascript'
    script.charset = 'utf-8'
    document.getElementsByTagName('head')[0].appendChild(script)
  },
  insertStylesheet:function(url){
    var link = document.createElement('link')
    link.href = url+"?"+PGPW.insertNumber
    link.media = "screen"
    link.rel = "stylesheet"
    link.type = "text/css"
    document.getElementsByTagName('head')[0].appendChild(link)
  },
  removeInsertedElement:function(insert){
    document.getElementsByTagName('head')[0].removeChild(insert)
  },


  //////////////////
  // Widget setup //
  //////////////////

  pageReady: false,
  waitingToRegister: [],
  addWidget:function(widgetClass, widget){
    JQ.extend(PGPW,widget)
    if (PGPW.pageReady) {
      PGPW.registerInstances(widgetClass)
    } else {
      PGPW.waitingToRegister.push(widgetClass)
    }
  },
  registerInstances:function(type){
    // We're going to loop through each widget on the page
    // and register its instance in PGPW.WidgetType.Instances
    JQ('.pagepow-'+type).not('.pagepow-registered').not('.pagepow-preview').each(function(){
      var widgetId = null, Widget = null, options = null
      // Get the widget's pagepow id
      widgetId = PGPW.getWidgetId(this)
      // Get the object of this widget's type
      Widget = PGPW.getWidgetObject(this)
      // Get the widget's instance id and in-page options
      eval('options = '+((JQ.trim(this.innerHTML) != "") ? PGPW.parseConfig(this.innerHTML) : null))

      // Set the html id for the instance, which will be the sanitized
      // instance name or 'widget' followed by -randomNumber
      this.id = this.id || ((options['name'] != null) ? 'w-'+options['name'].replace(/\W/ig,'-').toLowerCase()+'-' : 'widget-')+PGPW.randomNumber()

      // We need to make sure everything went ok, we need  to know
      // the html id, the widget id, an instance id, and the widget's
      // object was instantiated properly
      if (this.id == "" || widgetId == null || options['name'] == null || typeof Widget == "undefined") { return }
      
      // Add the instance options to its type's class
      if (typeof Widget.Instances == "undefined") {
        Widget.Instances = {}
      }
      Widget.Instances[this.id] = { Name: '', Options: {} }
      Widget.Instances[this.id].Name = options['name']
      JQ.extend(
        Widget.Instances[this.id].Options,
        PGPW.DefaultOptions[widgetId],
        ((options['options'] != null)?options['options']:null)
      )
      // Register this instance with its type's class
      Widget.register(widgetId,this)
      
      JQ(this).addClass('pagepow-registered')
    })
  },
  parseConfig:function(html){
    return html.match(/<script>[\s\n\r]*'\s*config(uration)?:[\s\n\r]*(\{([\n\r]|.)+?\})\s*'[\s\n\r]*<\/script>/i)[2]
  },


  ///////////////////////////////////
  // Shared widget utility methods //
  ///////////////////////////////////

  getWidgetType:function(instance){
    var widgetType = JQ(instance).getMatchingClasses(/^pagepow-(?!\d|widget)(.*)$/)[0].match(/^pagepow-(.*)$/)[1]
    var widgetObject = ""
    JQ.each(widgetType.split('-'),function(i,word){
      // Capitalize the first letter of each word
      widgetObject += word.substring(0,1).toUpperCase()+word.substring(1)
    })
    return widgetObject
  },
  getWidgetObject:function(instance){
    var widgetType = PGPW.getWidgetType(instance)
    return eval("PGPW."+widgetType)
  },
  getWidgetId:function(instance){
    return JQ(instance).getMatchingClasses(/^pagepow-(\d+)$/)[0].match(/^pagepow-(\d+)$/)[1]
  },
  getInstance:function(child){
    return JQ(child).parents('div.pagepow-widget')[0]
  },
  getInstanceHTMLId:function(instance){
    return ((typeof instance == "String")?instance:instance.id)
  },
  getInstanceWordyId:function(instance){
    var Widget = PGPW.getWidgetObject(instance)
    return Widget.Instances[PGPW.getInstanceHTMLId(instance)].Name
  },
  randomNumber:function(){
    return Math.floor(Math.random()*10000)
  },
  withBlocker:function(content, contentStyle, closerStyle){
    PGPW.removeBlocker()
    JQ('body').prepend('<div id="pgpw-blocker" class="pgpw-blocker" style="display:none;background:white;position:fixed;top:0;left:0;width:100%;height:100%;z-index:99999;opacity:0"></div><div id="pgpw-blocker-content" class="pgpw-blocker" style="display:none;position:fixed;top:25px;background:#eee;border:5px solid #ccc;width:400px;left:50%;margin-left:-200px;padding:15px;overflow:auto;z-index:999999"><a id="pgpw-blocker-close" style="position:absolute;top:0;right:0;font-size:11px;cursor:pointer;padding:3px 6px;background:#ccc;text-transform:uppercase;color:white;font-weight:bold;text-decoration:none">CLOSE</a>'+content+'</div>')
    if (JQ.browser.msie) {
      var pageSize = PGPW.getPageSize()
      var pageScroll = PGPW.getPageScroll()
      JQ('#pgpw-blocker').css({ position: 'absolute', width: pageSize[0], height: pageSize[1] })
      JQ('#pgpw-blocker-content').css({ position: 'absolute', top: pageScroll[1]+30+'px' })
    }
    if (contentStyle) { JQ('#pgpw-blocker-content').css(contentStyle) }
    if (closerStyle) { JQ('#pgpw-blocker-close').css(closerStyle) }
    JQ('#pgpw-blocker-close').add('#pgpw-blocker').click(function(){ PGPW.removeBlocker(true) })
    JQ('#pgpw-blocker').show().fadeTo(500, 0.5)
    JQ('#pgpw-blocker-content').show().fadeIn(500)
  },
  removeBlocker:function(fade){
    ((fade) ? JQ('.pgpw-blocker').fadeTo(500, 0, function(){ JQ('.pgpw-blocker').remove() }) : JQ('.pgpw-blocker').remove())
  },
  getPageSize:function(){
    // Returns array with page width, height and window width, height
    // Core code from - quirksmode.com
    // Edit for Firefox by pHaez
  	var xScroll, yScroll
  	if (window.innerHeight && window.scrollMaxY) {	
  		xScroll = window.innerWidth + window.scrollMaxX
  		yScroll = window.innerHeight + window.scrollMaxY
  	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
  		xScroll = document.body.scrollWidth
  		yScroll = document.body.scrollHeight
  	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
  		xScroll = document.body.offsetWidth
  		yScroll = document.body.offsetHeight
  	}
  	var windowWidth, windowHeight
    // console.log(self.innerWidth)
    // console.log(document.documentElement.clientWidth)
  	if (self.innerHeight) {	// all except Explorer
  		if(document.documentElement.clientWidth){
  			windowWidth = document.documentElement.clientWidth
  		} else {
  			windowWidth = self.innerWidth
  		}
  		windowHeight = self.innerHeight
  	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
  		windowWidth = document.documentElement.clientWidth
  		windowHeight = document.documentElement.clientHeight
  	} else if (document.body) { // other Explorers
  		windowWidth = document.body.clientWidth
  		windowHeight = document.body.clientHeight
  	}	
  	// for small pages with total height less then height of the viewport
  	if(yScroll < windowHeight){
  		pageHeight = windowHeight
  	} else { 
  		pageHeight = yScroll
  	}
    // console.log("xScroll " + xScroll)
    // console.log("windowWidth " + windowWidth)
  	// for small pages with total width less then width of the viewport
  	if(xScroll < windowWidth){	
  		pageWidth = xScroll		
  	} else {
  		pageWidth = windowWidth
  	}
    // console.log("pageWidth " + pageWidth)
  	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
  	return arrayPageSize
  },
  getPageScroll:function(){
    // Returns array with x,y page scroll values.
    // Core code from - quirksmode.com
  	var xScroll, yScroll
  	if (self.pageYOffset) {
  		yScroll = self.pageYOffset
  		xScroll = self.pageXOffset
  	} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
  		yScroll = document.documentElement.scrollTop
  		xScroll = document.documentElement.scrollLeft
  	} else if (document.body) {// all other Explorers
  		yScroll = document.body.scrollTop
  		xScroll = document.body.scrollLeft
  	}
  	arrayPageScroll = new Array(xScroll,yScroll) 
  	return arrayPageScroll
  },
  


  ////////////////////
  // Cookie methods //
  ////////////////////

  // set and get methods thankfully lifted from quirksmode
  setRecordsCookie:function(instance,code){
    var records = ((PGPW.getRecordsCookie()) ? PGPW.getRecordsCookie() : {})
    records[PGPW.getWidgetId(instance)+'-'+PGPW.getInstanceWordyId(instance)] = ((code)?code:true)
		var date = new Date();
		date.setTime(date.getTime()+(365*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
    document.cookie = "records="+JQ.toJSON(records)+expires+"; path=/"
  },
  getRecordsCookie:function(){
    var name = "records="
    var cookies = document.cookie.split(';')
    for(var i=0;i<cookies.length;i++) {
      var c = cookies[i]
      while (c.charAt(0)==' ') {
        c = c.substring(1,c.length)
      }
      if (c.indexOf(name) == 0) {
        return JQ.parseJSON(c.substring(name.length,c.length))
      }
    }
    return null
  },
  checkRecordsCookieFor:function(instance){
    var records = PGPW.getRecordsCookie()
    if (records && typeof records[PGPW.getWidgetId(instance)+'-'+PGPW.getInstanceWordyId(instance)] != "undefined") {
      return records[PGPW.getWidgetId(instance)+'-'+PGPW.getInstanceWordyId(instance)]
    } else {
      return false
    }
  }

})

JQ(function(){
  PGPW.pageReady = true
  JQ.each(PGPW.waitingToRegister,function(){
    PGPW.registerInstances(this)
  })
})
