/* 
  Algo: a dekstop environment look-a-like in your web browser
  Copyright (C) 2009  Niels Serup
  
	This file is part of Algo.

	Algo is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Algo is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Algo.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
  This is the scr_window class. It takes care of creating windows and
  editing windows. When a window has been created, it can be minimized,
  maximized and closed by the prototype functions of this class.
*/
function scr_window(title, icon, state, options, width, height, xpos, ypos, resizeable) {
  if (title == undefined) return // The title is the identifier - a must
  if (icon == undefined) var icon = false // Defaults to no icon
  if (state == undefined || state == -1) var state = 1 // 0 = minimized, 1 = normal, 2 = maximized
  if (options == undefined || options == -1) var options = [1, 1, 1] // Both minimizable, maximizeable and closeable
  if (width == undefined || width == -1) var width = 500 // Default width
  if (height == undefined || height == -1) var height = 350 // Default height
  if (xpos == undefined || xpos == -1) var xpos = (w - width) / 2 // Places it center
  if (ypos == undefined || ypos == -1) var ypos = (sh - height) / 2 // Places it in the middle
  if (resizeable == undefined || resizeable == -1) var resizeable = true // Resizable as default
  
  if (width < width_min) width = width_min // Limits
  if (height < height_min) height = height_min // Limits
  
  // Uniqueifyes the variables
  this.title = title
  this.icon = icon
  this.options = options
  this.width = width
  this.height = height
  this.resizeable = resizeable
  
  /* Creates two unique numbers. "num" will change if a window opened before
     this window is closed, while onum will never change */
  this.num = scr.len
  this.onum = scr.olen
  
  // Creates the appbox in the appbox navbar
  this.appbox = document.createElement('div')
  this.appbox.rel = wnds.length // Accesible by JavaScript
  this.appbox.onclick = function() {
    // Minimize if visible and current
    // Change focus if visible but not current
    // Unminimize if not visible (the "un"-part happens automatically)
    if (wnds[this.rel].visible) {
      if (wnds[this.rel].appbox.className == 'current')
        wnds[this.rel].minimize(this.rel)
      else
        scr.change_focus(this.rel)
    }
    else
      wnds[this.rel].minimize(this.rel)
    
  }
  this.appbox.innerHTML = title
  // Appending it
  navi[posis['appboxes']].appboxes.appendChild(this.appbox)
  
  
  /* The following code creates all the neccesary elements for a window to
     exist. It's fairly straight-forward, but it takes up a lot of space */
  var elems, belems, el, tmp, i, c
  this.elem = document.createElement('div')
  this.elem.className = 'window'
  
  el = 13 // The number of elements to be created
  if (icon) el++
  
  tmp = 0
  if (options[0]) tmp++
  if (options[1]) tmp++
  if (options[2]) tmp++
  this.optboxes = tmp
  
  if (tmp > 0) el++
  elems = new Array(el)
  belems = new Array(tmp)
  
  // Borders
  for (i = 0; i < 8; i++) {
    elems[i] = document.createElement('div')
    elems[i].className = global_directions_dt[i]
    if (i != 1) {
      if (resizeable) {
        elems[i].rel = i + ''
        elems[i].onmousedown = function() {
          if (wnds[this.parentNode.rel].normal)
            scr.adjust_start(this.parentNode.rel, this.rel)
        }
        elems[i].onmouseup = function() {
          scr.adjust_end()
        }
      }
    }
  }
  
  // Title + text + icon + options
  elems[8] = document.createElement('div')
  elems[8].className = 'title'
  elems[8].innerHTML = this.title
  
  elems[9] = document.createElement('div')
  elems[9].className = 'handle'
  elems[9].onmousedown = function() {
    if (wnds[this.parentNode.rel * 1].normal) {
      scr.move_start(this.parentNode.rel * 1)
    }
  }
  elems[9].onmouseup = function() {
    scr.move_end()
  }
  elems[9].ondblclick = function() {
    wnds[this.parentNode.rel * 1].maximize()
  }
  
  elems[10] = document.createElement('div')
  elems[10].className = 'resize_handle'
  if (resizeable) {
    elems[10].rel = '1'
    elems[10].onmousedown = function() {
      if (wnds[this.parentNode.rel * 1].normal)
        scr.adjust_start(this.parentNode.rel * 1, this.rel * 1)
    }
    elems[10].onmouseup = function() {
      scr.adjust_end()
    }
  }
  else
    this.elem.className += ' nrsz' // Seen by a css file
  if (!ie) {
    elems[11] = document.createElement('object')
    elems[11].data = 'pages/links.php?title=' + escape(title) + '&num=' + this.onum
    elems[11].type = 'text/html'
  }
  else {
    elems[11] = document.createElement('iframe')
    elems[11].src = 'pages/links.php?title=' + escape(title) + '&num=' + this.onum
    elems[11].frameBorder = '0'
  }
  elems[11].className = 'data'
  
  elems[12] = document.createElement('div')
  elems[12].className = 'data_overlay'
  
  if (icon) {
    elems[13] = document.createElement('div')
    elems[13].className = 'icon'
    elems[13].style.backgroundImage = 'url(\'pages/links.php?title=' + escape(title) + '&type=png\')'
  }
  
  if (this.optboxes > 0) {
    // If any options at all
    tmp = elems.length - 1
    elems[tmp] = document.createElement('div')
    elems[tmp].className ='options'
    
    c = 0
    for (i = 0; i < 3; i++) {
      if (options[i]) {
        belems[i] = document.createElement('div')
        belems[i].className = global_options[i] // Refer to onload.js
        if (global_options[i] == 'minimize') belems[i].onclick = function() {
          wnds[this.parentNode.parentNode.rel * 1].minimize()
        }
        else if (global_options[i] == 'maximize') belems[i].onclick = function() {
          wnds[this.parentNode.parentNode.rel * 1].maximize()
        }
        else belems[i].onclick = function() {
          wnds[this.parentNode.parentNode.rel * 1].close()
        }
        elems[tmp].appendChild(belems[i])
        c++
      }
    }
  }
  
  // All clickable elements need elem.rel to determine what window to change
  this.elem.rel = wnds.length
  
  this.elem.onmousedown = function() {
    scr.change_focus(this.rel * 1)
  }
  
  this.elem.style.left= xpos + 'px'
  this.elem.style.top = ypos + 'px'
  
  for (i = 0; i < el; i++) {
    // Append all created elements
    this.elem.appendChild(elems[i])
  }
  this.len = this.elem.childNodes.length
  
  scr.elem.appendChild(this.elem)
  
  this.visible = true
  this.normal = true
  if (state == 0) this.minimize()
  
  this.update() // Adjust widths, heights, etc.
  this.update_appbox() // The same with the appbox
  
  if (state == 2) this.maximize()
}

scr_window.prototype.update = function() {
  /* This function updates the dimensions of the subelements of a window.
     scr holds standard information such as the general margin, while the
     window itself has some info about width, height, icons, etc. */
  var tmp, el
  
  el = this.cn('tl')
  el.style.width = scr.margin_g + 'px' // margin_g is the general margin
  el.style.height = scr.hheight + 'px' // hheight is the header height
  
  el = this.cn('t')
  el.style.left = scr.margin_g + 'px'
  el.style.width = this.width - scr.margin_g * 2 + 'px'
  el.style.height = scr.hheight + 'px'
  
  el = this.cn('tr')
  el.style.left = this.width - scr.margin_g + 'px'
  el.style.width = scr.margin_g + 'px'
  el.style.height = scr.hheight + 'px'
  
  el = this.cn('r')
  el.style.top = scr.hheight + 'px'
  el.style.left = this.width - scr.margin_g + 'px'
  el.style.width = scr.margin_g + 'px'
  el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
  
  el = this.cn('br')
  el.style.top = this.height - scr.margin_g + 'px'
  el.style.left = this.width - scr.margin_g + 'px'
  el.style.width = scr.margin_g + 'px'
  el.style.height = scr.margin_g + 'px'
  
  el = this.cn('b')
  el.style.top = this.height - scr.margin_g + 'px'
  el.style.left = scr.margin_g + 'px'
  el.style.width = this.width - scr.margin_g * 2 + 'px'
  el.style.height = scr.margin_g + 'px'
  
  el = this.cn('bl')
  el.style.top = this.height - scr.margin_g + 'px'
  el.style.width = scr.margin_g + 'px'
  el.style.height = scr.margin_g + 'px'
  
  el = this.cn('l')
  el.style.top = scr.hheight + 'px'
  el.style.width = scr.margin_g + 'px'
  el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
  
  el = this.cn('title')
  el.style.top = scr.margin_g + 'px'
  el.style.height = scr.hheight - scr.margin_g + 'px'
  if (this.icon) tmp = scr.bw + scr.margin_t
  else tmp = 0
  el.style.left = scr.margin_g + scr.margin_t + tmp + 'px'
  el.style.width = this.width - scr.margin_g * 2 - scr.margin_t * 2 - this.optboxes * (scr.bw + scr.margin_t) - tmp + 'px'

  el = this.cn('handle')
  el.style.top = scr.margin_g + 'px'
  el.style.height = scr.hheight - scr.margin_g + 'px'
  el.style.left = scr.margin_g + scr.bw + scr.margin_t + 'px'
  el.style.width = this.width - scr.margin_g * 2 - this.optboxes * (scr.bw + scr.margin_t) - tmp + 'px'

  el = this.cn('resize_handle')
  el.style.left = scr.margin_g + 'px'
  el.style.width = this.width - scr.margin_g * 2 + 'px'
  el.style.height = scr.margin_g + 'px'

  el = this.cn('data')
  el.style.top = scr.hheight + 'px'
  el.style.left = scr.margin_g + 'px'
  el.style.width = this.width - scr.margin_g * 2 + 'px'
  el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
  
  el = this.cn('data_overlay')
  el.style.top = scr.hheight + 'px'
  el.style.left = scr.margin_g + 'px'
  el.style.width = this.width - scr.margin_g * 2 + 'px'
  el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
  
  if (this.icon) {
    el = this.cn('icon')
    el.style.top = scr.margin_g + 'px'
    el.style.left = scr.margin_g + scr.margin_t + 'px'
    el.style.width = scr.bw + 'px' // bw is the box width
    el.style.height = scr.bh + 'px' // bh is the box height
  }

  el = this.cn('options')
  if (el) {
    el.style.top = scr.margin_g + 'px'
    el.style.left = this.width - this.optboxes * (scr.bw + scr.margin_t) - scr.margin_g + 'px'
    el.style.width = this.optboxes * (scr.bw + scr.margin_t) - scr.margin_t + 'px' // margin_t is the margin used in the top of the window
    el.style.height = scr.bh + 'px'
    
    var elc = el.childNodes
    var elcl = elc.length
    for (var i = 0; i < elcl; i++) {
      elc[i].style.left = i * (scr.bw + scr.margin_t) + 'px'
      elc[i].style.width = scr.bw + 'px'
    }
  }
}

scr_window.prototype.update_appbox = function() {
  this.appbox.style.height = navi[posis['appboxes']].height - appbox_padding * 2 - appbox_margin * 2 - appbox_border * 2 + 'px'
}

scr_window.prototype.cn = function(what) {
  /* This function is a smart one. It returns a pointer to the node which
     has the class specified by "what". If it's not found, the returned node
     is "fallback", which does nothing but at the same time makes sure no
     errors pop up. */
  var i = 0
  var ok = false
  var nodes = this.elem.childNodes
  var node = fallback
  while (i < this.len && !ok) {
    if (nodes[i].className == what) {
      node = nodes[i]
      ok = true
    }
    i++
  }
  return node
}

scr_window.prototype.settitle = function(title) {
  // Sets the title of the window and the appbox associated with the window
  this.cn('title').innerHTML = title
  this.appbox.innerHTML = title
}

scr_window.prototype.minimize = function() {
  /*
    Minimizes if visible
    Unminimizes if not visible
  */
  if (this.visible) {
    this.visible = false
    this.elem.style.display = 'none'
    scr.change_focus(this.num, 1)
  }
  else {
    this.visible = true
    this.elem.style.display = 'block'
    scr.change_focus(this.num)
  }
}

scr_window.prototype.maximize = function() {
  /*
    Maximizes if normal
    Unmaximizes if already maximized
  */
  if (this.normal) {
    this.normal = false
    this.savedpos = [this.elem.offsetLeft, this.elem.offsetTop, this.width, this.height]
    this.elem.style.left = -scr.margin_g + 'px'
    this.elem.style.top = 0
    this.width = w + scr.margin_g * 2
    this.height = sh + scr.margin_g
    this.elem.className = 'window window_max'
  }
  else {
    this.normal = true
    this.elem.style.left = this.savedpos[0] + 'px'
    this.elem.style.top = this.savedpos[1] + 'px'
    this.width = this.savedpos[2]
    this.height = this.savedpos[3]
    this.elem.className = 'window'
    if (!this.resizeable) this.elem.className += ' nrsz'
  }
  this.update()
}

scr_window.prototype.close = function() {
  // Changes focus with det set to 2, which in turn removes the element
  scr.change_focus(this.num, 2)
}

scr_window.prototype.renum = function(n) {
  /* This function changes the "num" variable and the attributes that use it.
     The "num" variable will in some cases have to be changed when a window
     closes. */
  this.num += n
  this.elem.rel = this.num
  this.appbox.rel = this.num
}