// tab-control:
// Initialize by scanning the page for all tab controls (=nodes with class tab-control)
// Then scan each node for tab-header and tab-page nodes, and assign an onclick
// to each one in sequence

// globals: must be set by enclosing page
// imagesBaseDir: Url of the base images folder
var idCounter = 1;		// Brukes til noe message-greier
var debug = 1;
var threadIdCounter = 0;
var threads = {};
function Thread(owner) {
	var threadId = threadIdCounter++;
	threads[threadId] = owner;
	var timer;

    // Calls the given function on the owner object
  	// after a specficed amount of time  
	this.setTimeout = function (func, ms) {
		timer = setTimeout("threads[" + threadId + "]." + func, ms);
	};
	this.cancel = function () {
		if (timer) {
			clearTimeout(timer);
		}
		delete threads[threadId];
	};
}
function Color(hexOrArray) {
	var isString = (hexOrArray.length == 6);
	var hex = "";
	var values = [];
	if (isString) {
		hex = hexOrArray;
		for (var j = 0; j < 3; j++) {
			var s = hex.substr(j * 2, 2);
			values[j] = parseInt(s, 16);
		}
	} else {
		for (var j = 0; j < 3; j++) {
			values[j] = hexOrArray[j];
			hex += ((values[j] < 16) ? "0" : "") + Math.floor(values[j]).toString(16);
		}
	}
  
  // Returns one of the r,g,b values as an int
	this.getValue = function (j) {
		return values[j];
	};
  
  // Returns the hex value
	this.hexValue = function () {
		return hex;
	};
}
function Fader(fadeElem) {
	var thread = new Thread(this);
  
  // This is list of steps that will be used for the color to fade out
	var colors = [[0, new Color("FFED8C")], [0.15, new Color("FFFFFF")], [0.4, new Color("FFFFFF")], [1, new Color("FFED8C")]];
	var fraction = 0;
	var speed = 0.1;
	var intervalMs = 200;
  
  // Interpolate between color a and b (0 <= i <= 1)
	function interpolate(a, b, i) {
		var values = [];
		for (var j = 0; j < 3; j++) {
			values[j] = (a.getValue(j) * (1 - i)) + (b.getValue(j) * i);
		}
		return new Color(values);
	}
	function getColor() {
    // Check bounds
		if (fraction < 0) {
			return colors[0][1].hexValue();
		}
		if (fraction >= 1) {
			return colors[colors.length - 1][1].hexValue();
		}
    // Find nearest two colors
		for (var i = 0; i < colors.length - 1; i++) {
			var a = colors[i];
			var b = colors[i + 1];
			if ((a[0] <= fraction) && (b[0] > fraction)) {
				return interpolate(a[1], b[1], ((fraction - a[0]) / (b[0] - a[0]))).hexValue();
			}
		}
	}
	this.start = function () {
		this.step();
	};
	this.step = function () {
  
    // Set color
		var color = getColor();
		fadeElem.style.backgroundColor = "#" + color;

    // Wait for next iteration
		fraction += speed;
		if (fraction > 1) {
			this.stop();
		} else {
			thread.setTimeout("step()", intervalMs);
		}
	};
	this.stop = function () {
		thread.cancel();
    //fadeElem.style.backgroundColor = "";
	};
}
function sjekkStartFading(formElem) {

  // Finn fade-element
	var elems = document.getElementsByClassName("heltny", formElem);
	for (var i = 0; i < elems.length; i++) {
		var fader = new Fader(elems[i]);
		fader.start();
	}
}
function doubleDigit(d) {
	d = "" + d;
	while (d.length < 2) {
		d = "0" + d;
	}
	return d;
}
function dateString(date) {
	return doubleDigit(date.getDate()) + "." + doubleDigit(date.getMonth() + 1) + "." + date.getFullYear();
}
function getTodaysDate() {
	return dateString(new Date());
}
function AjaxProgress(parentElem) {
	var thread = new Thread(this);
	function getProgressElem() {
		var elems = document.getElementsByClassName("progress", parentElem);
		return (elems.length ? elems[0] : null);
	}
	var progressElem = getProgressElem();
	this.show = function () {
		if (progressElem) {
			progressElem.innerHTML = "<img src='" + imagesBaseDir + "spinner.gif' />";
		}
	};
	this.start = function () {
		thread.setTimeout("show()", 500);
	};
	this.stop = function () {
		thread.cancel();
		if (progressElem) {
			progressElem.innerHTML = "";
		}
	};
}

function showError(errorText, formElem) {
    var errorElem = null;
	var elems = document.getElementsByClassName("ErrorWidget", (formElem ? formElem : document.body));
    if (elems.length) {
	  errorElem = elems[0];
	}
	if (errorElem) {
	    var p = new PositionManager(formElem);
		errorElem.innerHTML = errorText;
		Element.removeClassName(errorElem, "hidden");
		p.restore();
	} else {
		alert(errorText);
	}
}

function ajaxSubmit(actionUrl, parameters, formElem, handling) {

    // Husk form id
    var formId = formElem.id;

    // Start an image spinning animation
	var progress = new AjaxProgress(formElem);
	progress.start();
	if (handling) {
		parameters += "&handling=" + handling;
	}
	var errorText = "Det oppsto en feil. ";
	if ((handling == "slett") || (!handling)) {
		errorText += "Endringene ble ikke lagret. ";
	}
	errorText += "\n\nHvis problemet vedvarer, pr&oslash;v &aring; logge ut og inn igjen. ";
	var ajax = new Ajax.Request(actionUrl, {method:"post", parameters:parameters, onSuccess:(function (req) {
		progress.stop();
		parsed = parseResponse(req.responseText);
		var id = parsed.id;
	    var p = new PositionManager($(id));
		$(id).innerHTML = parsed.html;
		$(id).setAttribute("controller", null);
		p.restore();
		sjekkStartFading($(id));
		if(formId && $(formId)) { focusElemInForm($(formId)); } else { focusFirstInput(); }
	}).bind(this), onFailure:function (req) {
		progress.stop();
		showError(errorText, formElem);
	}, onException:function (t, e) {
		progress.stop();
		showError(errorText, formElem);
	}});
}

// strip away the container div
function parseResponse(responseText) {
  var inner = "";
  var id = "";
  var r = /<([^>]*)>((\s|\S)*)<\/[^>]+>/i;
  if (responseText.match(r)) {
    inner = RegExp.$2;
    var s = / id=[ \'\"]*([^ \"\']*)/i;
    if (RegExp.$1.match(s)) {
      id = RegExp.$1;
    }
  }
  return {id:id, html:inner};
}


function dumpObject(e) {
	var s = "";
	s += e;
	s += ": ";
	for (var i in e) {
		s += " " + i + "=" + e[i];
	}
	return s;
}
function getId() {
	return "id-" + (idCounter++);
}

// Set focus to the first visible textbox on the page
function focusFirstInput() {

  // for each form
	for (f = 0; f < document.forms.length; f++) {
		var formElem = document.forms[f];
  
  	// Check that this form isn't hidden
		var tabElem = getClassUp(formElem, "tabPage");
		if ((formElem.id == "SporreWidget") || ((tabElem != null) && (Element.hasClassName(tabElem, "hidden")))) {
			continue;
		}
		focusElemInForm(formElem);
	}
}

// Sets the focus to the right element in the form
function focusElemInForm(formElem) {
	var focusElem = null;

  // for each element in each form
	for (i = 0; i < formElem.length; i++) {
		var inputElem = formElem[i];
	  
    // if it's a text box
		var t = inputElem.type;
		if (((t == "text") || (t == "password") || (t == "button") || (t == "submit")) && (inputElem.disabled != true) && (!inputElem.getAttribute("readonly"))) {

      // select if not focused anything, or if selected something without error
			var hasError = (Element.hasClassName(inputElem, "errorField") || Element.hasClassName(inputElem.parentNode, "errorField"));
			if ((!focusElem) || hasError) {
				focusElem = inputElem;
				if (hasError) {
      	  // If found an input with an error, don't look any more
					break;
				}
			}
		}
	}
	if (focusElem) {
		focusInput(focusElem);
	}
}
var globalFocusElem = null;
function focusInput(elem) {
	globalFocusElem = elem;
	setTimeout("try { globalFocusElem.focus() } catch(err) { }", 100);
	//elem.style.border = "3px dashed blue";
	//alert("set focus to elem.id=" + elem.id + " elem-tagName=" + elem.tagName);
}

// Get the INPUT field belonging to a date elem
function getDateField(dateElem) {
	return dateElem.getElementsByTagName("INPUT")[0];
}

// Called when the user clicks the calendar image
function calendarClick(imgElem) {
	var dateElem = getClassUp(imgElem, "date");
	var formElem = getTagUp(dateElem, "FORM");
	var defaultValue = "";
	var elems = document.getElementsByClassName("date", formElem);
	for (var i = 0; i < elems.length; i++) {
		var elem = elems[i];
		if ((elem == dateElem) && (i >= 1)) {
        // Treat earlier 
			defaultValue = getDateField(elems[i - 1]).value;
			break;
		}
	}
	popUpCalendar(imgElem, getDateField(dateElem), dateFormat, defaultValue);
}

// e is the button clicked
function buttonClick(button, handling) {
	var formElem = getTagUp(button, "FORM");
	submitForm(formElem, handling);
	return false;
}

// formElem: an actual elem
function submitForm(formElem, handling) {
	var actionUrl = formElem.action;
	var parameters = Form.serialize(formElem);
	ajaxSubmit(actionUrl, parameters, formElem, handling);
}

// formElem: an actual elem
function erFormSkjult(formElem, varSkjult) {
	var parameters = Form.serialize(formElem);
	return (parameters.search("skjult=true") != -1);
}
function getClassUp(e, name) {
	if (!(e && e.tagName)) {
		return null;
	}
	//alert(e.tagName+":"+e.className);
	if (Element.hasClassName(e, name)) {
		return e;
	}
	return getClassUp(e.parentNode, name);
}
function getTagUp(e, name) {
	if (!(e && e.tagName)) {
		return null;
	}
	if (e.tagName == name) {
		return e;
	}
	return getTagUp(e.parentNode, name);
}

// Gets one element by tag name which is
// a descendant of the name given
function getOneElementByTagName(e, name) {
	var someNodeList = e.getElementsByTagName(name);
	var nodes = $A(someNodeList);
	var result = null;
	nodes.each(function (node) {
		result = node;
	});
	return result;
}

var currentHeader;
var currentPage;
function clickHeader(header, pageId) {
	/* Bytter om på rekkefølgen av 'tab'-rader */
	var cElmt = header;
	var table = cElmt.parentNode.parentNode;
	var intro = document.getElementById("titlerIntro");
	var iStat = 0;
	if (intro) {
		var removed = table.removeChild(cElmt.parentNode);
		table.appendChild(removed);
		if (intro.parentNode == removed) {
			intro.parentNode.removeChild(intro);
			iStat = 1;
		}
		if (iStat == 1) {
			var n = table.childNodes;
			var l = n.length;
			for (var m = 0; m < l; m++) {
				if (iStat == 1) {
					if (n[m].nodeType == 1) {
						n[m].appendChild(intro);
						iStat = 0;
					}
				}
			}
		}
	}
	/* Original kode */
	var page = $(pageId);
	if (page == currentPage) {
		closePage(currentPage, currentHeader, true);
		currentPage = null;
		currentHeader = null;
	} else {
	    var p = new PositionManager(header);
		closePage(currentPage, currentHeader, false);
		openPage(page, header, (!currentPage));
		p.restore(page);
		currentPage = page;
		currentHeader = header;
		var formElem = getOneElementByTagName(page, "form");
		if (erFormSkjult(formElem)) {
			submitForm(formElem, "vis");
		} else {
			focusElemInForm(formElem);
		}
	}
	return false;
}
var hasClicked = {};
var hiddenClass = "hidden";
var selectedClass = "selected";
var effectDuration = 0.5;
function closePage(page, header, doEffect) {
	doEffect = false;
	Element.removeClassName(header, selectedClass);
	if (doEffect) {
		page.style.display = "block";
	}
	Element.addClassName(page, hiddenClass);
	if (doEffect) {
		Effect.Fade(page, {duration:effectDuration});
	}
}
function openPage(page, header, doEffect) {
	doEffect = false;
  // Make the transion longer by adding options.
	Element.addClassName(header, selectedClass);
	if (doEffect) {
		page.style.display = "none";
	}
	Element.removeClassName(page, hiddenClass);
	if (doEffect) {
		Effect.Appear(page, {duration:effectDuration});
	}
	//ensureVisible(page);
}

function getBodyHeight() {
  if (self.innerHeight) { return self.innerHeight; } // all except Explorer
  else if (document.documentElement && document.documentElement.clientHeight) { return document.documentElement.clientHeight; } // Explorer 6 Strict Mode
  else if (document.body) { return document.body.clientHeight; } // other Explorers
}

function getBodyScroll() {
  if (self.pageYOffset) { return self.pageYOffset; } // all except Explorer
  else if (document.documentElement && document.documentElement.scrollTop) { return document.documentElement.scrollTop; } // Explorer 6 Strict
  else if (document.body) { return document.body.scrollTop; } // all other Explorers
}


function RelativePosition(e) {

  this.body = [getBodyScroll(), getBodyHeight()]; 
  this.elem = [Position.cumulativeOffset(e)[1], e.offsetHeight];

  this.apparentTop = function() {
    return this.elem[0] - this.body[0];
  };
  
  // Ensures object is visible
  this.needsDelta = function() {
    var now = this.body[0] + this.body[1];
    var needs = this.elem[0] + this.elem[1];
    return needs-now;
  };
  
  /*
  this.toString = function() {
    return "body=["+this.body[0]+","+this.body[1]+"], elem=["+this.elem[0]+","+this.elem[1]+"], apparentTop="+this.apparentTop()+", needsDelta="+this.needsDelta();
  }
  */
    
}

// Takes care of objects not jumping around
// when opening or closing tabs
function PositionManager(e) {

  var p = new RelativePosition(e);
  var g = $("heightGuard");
  if(g) { g.style.top = (document.body.offsetHeight-1) + "px"; g.style.display = "block"; }

  // Ensures object is visible
  this.show = function() {
    if(p.needsDelta()) { e.scrollIntoView(false); }
	if(g) { g.style.display = "none"; }
  };

  // Restores original position
  // But also ensures that v is visible
  this.restore = function(v) {
    if(!v) { v = e; }
    var q = new RelativePosition(e);
    // delta for restoring
    var restoreDelta = q.apparentTop() - p.apparentTop();
    // Ensure v is visible
    var visibleDelta = new RelativePosition(v).needsDelta();
    var delta = Math.max(restoreDelta, visibleDelta);
    /*
    var x = "";
    x += p.toString()+"\n";
    x += q.toString()+"\n";
    x += "restoreDelta="+restoreDelta+"\n";
    x += "visibleDelta="+visibleDelta+"\n";
    x += "delta="+delta+"\n";
    alert(x);
    */
    // Scroll
    if(delta) { window.scrollBy(0, delta); }    
	if(g) { g.style.display = "none"; }
  };
}


// Ensures that element e is visible,
// if necessary by scrolling
function ensureVisible(e) {
  new PositionManager(e).show();
}



// Funksjon for aa gjemme eller vise et felt i en form
function showInput(formElem, field, show, endcolor, suppressEffect) {
	var elem = findField(formElem, field).ancestors()[1];
	if (show) {
		Element.removeClassName(elem, "hidden");
		if (!(suppressEffect || elem.getAttribute("currentEffect"))) {
			elem.setAttribute("currentEffect", new Effect.Highlight(elem, {endcolor:endcolor, afterFinish:function () {
				elem.removeAttribute("currentEffect");
			}}));
		}
	} else {
		Element.addClassName(elem, "hidden");
	}
}
		
// Oppdater visning av privatperson/firma rader
function visPrivatperson(radioElem, show, endcolor, suppressEffect) {
	var formElem = getTagUp(radioElem, "FORM");
	showInput(formElem, "fornavn", show, endcolor, suppressEffect);
	showInput(formElem, "etternavn", show, endcolor, suppressEffect);
	showInput(formElem, "firma", !show, endcolor, suppressEffect);
	if(findField(formElem, "att") != null) {
		showInput(formElem, "att", !show, endcolor, suppressEffect);
		showInput(formElem, "co", show, endcolor, suppressEffect);
	}
}

function visUtfyllFakturaadresse(sender, suppressEffect) {

    var show = sender.checked;
	var formElem = getTagUp(sender, "FORM");
  	var elem = document.getElementsByClassName("gjemmer", formElem)[0];
  	if(!elem.getAttribute("currentEffect")) {
  	  if(suppressEffect) { 
  	    showElem(elem, sender.checked);
  	  } else if(show) {
  	      elem.setAttribute("currentEffect", new Effect.BlindDown(elem, {duration:0.5, afterFinish:function () {
		  	elem.removeAttribute("currentEffect"); showElem(elem, sender.checked);
		  }}));
      } else {
  	    elem.setAttribute("currentEffect", new Effect.BlindUp(elem, {duration:0.5, afterFinish:function () {
		  elem.removeAttribute("currentEffect"); showElem(elem, sender.checked);
		}}));
  	  }
  	}
}

function showElem(elem, show) {
  	elem.style.display = (show ? "block" : "none");
}

function findField(formElem, field) {
  return Form.getInputs(formElem, null, "endring." + field)[0];
}
