function Cache(form) {
  this.form = form;
  this.form.cache = this;
  this.failedRetries = 0;
  this.failedMaxRetries = 50;
}
Cache.prototype = new Object();
// Alap funkció élesítése, cookieból cookiba.
Cache.prototype.initCacheable = function () {
  Event.observe(this.form, 'submit', callback(this, this.get));
  this.flush();
}
Cache.prototype.setCookie = function (value) {
  createCookie(this.form.name, value);
}
Cache.prototype.getCookie = function () {
  return decodeURIComponent(readCookie(this.form.name));
}
Cache.prototype.getCache = function () {
  var cache = new Object();
  
  for (var i = 0; i < this.form.elements.length; i++) {
    if (this.form.elements[i].offsetWidth != 0 || this.form.elements[i].type == "hidden") {
      var value = null;
      if (this.form.elements[i].type == "text" 
          || this.form.elements[i].type == "hidden" 
          || this.form.elements[i].type == "textarea" 
          || this.form.elements[i].type == "select-one") {
        if (this.form.elements[i].value != '') value = this.form.elements[i].value;
      } else if (this.form.elements[i].type == "checkbox" 
                || this.form.elements[i].type == "radio") {
        if (this.form.elements[i].checked) {
          value = this.form.elements[i].value;
          //temp
          if (this.form.elements[i].value == "on") value = "t";
        }
      } else if (this.form.elements[i].type == "select-multiple") {
        for (var j = 0; j < this.form.elements[i].options.length; j++) {
          if (this.form.elements[i].options[j].selected) value = this.form.elements[i].options[j].value;
        }
      }

      if (value) {
        var name = this.form.elements[i].name;
        var multi = false;
        var sub_name = null;
        var a = name.indexOf('[');
        var b = name.indexOf(']');
        if (a != -1) {
          multi = true;
          if (b - a != 1) sub_name = name.substring(a + 1, b);
          name = name.substring(0, a);
        }

        if (multi) {
          if (sub_name) {
            if (!cache[name]) cache[name] = new Object();
            cache[name][sub_name] = value;
          } else {
            if (!cache[name]) cache[name] = new Array();
            cache[name].push(value);
          }
        } else {
          cache[name] = value;
        }
      }
    } else {
      // Rejtett elemet se keselni, se küldeni nem kell.
      this.form.elements[i].value = "";
    }
  }
  return cache;
}
Cache.prototype.flushCache = function (cache) {
  var failed = null;
  for (var i in cache) {
    switch (cache[i].constructor) {
      case String:
        var elements = document.getElementsByName(i);
        if (elements.length) {
          var changed = false;
          if (elements[0].type == "checkbox" || elements[0].type == "radio") {
            //temp
            if (cache[i] == "on") cache[i] = "t";
            if (elements[0].value == cache[i] && !elements[0].checked) {
              changed = true;
              elements[0].checked = true;
            }
          } else {
            if (elements[0].value != cache[i]) {
              changed = true;
              elements[0].value = cache[i];
              // Sikertelenség esetén későbbre hagyjuk.
              if (elements[0].value != cache[i]) {
                Event.observe(elements[0], "focus", function(value){
                  var inited = false;
                  return function(){
                    if (!inited) {
                      this.value = value;
                      inited = true;
                    }
                  }
                }(cache[i]));
              }
            }
          }
          // Ellenőrizzük a függőségeket.
          if (changed) {
            if (elements[0].dependency) {
              for (var l = 0; l < elements[0].dependency.length; l++) {
                elements[0].dependency[l].check();
              }
            }
            if (elements[0].tree) elements[0].tree.check(elements[0]);
          }
        } else {
          // Ha még nem létezik ilyen elem, későbbre hagyjuk.
          if (!failed) failed = new Object();
          failed[i] = cache[i];
        }
        break;
      case Array:
        var elements = document.getElementsByName(i + "[]");
        if (elements.length) {
          for (var j = 0; j < elements.length; j++) {
            if (elements[j].type == "checkbox" || elements[j].type == "radio") {
              for (var k = 0; k < cache[i].length; k++) {
                //temp
                if (cache[i][k] == "on") cache[i][k] = "t";
                if (elements[j].value == cache[i][k]) elements[j].checked = true;
              }
            } else {
              elements[j].value = cache[i][j];
            }
            // Ellenőrizzük a függőségeket.
            if (elements[j].dependency) {
              for (var l = 0; l < elements[j].dependency.length; l++) {
                elements[j].dependency[l].check();
              }
            }
            if (elements[j].tree) elements[j].tree.check(elements[j]);
          }
        } else {
        }
        break;
      case Object:
        for (var j in cache[i]) {
          var elements = document.getElementsByName(i + "[" + j + "]");
          if (elements.length) {
            if (elements[0].type == "checkbox" || elements[0].type == "radio") {
              //temp
              if (cache[i][j] == "on") cache[i][j] = "t";
              if (elements[0].value == cache[i][j]) elements[0].checked = true;
            } else {
              elements[0].value = cache[i][j];
            }
            // Ellenőrizzük a függőségeket.
            if (elements[0].dependency) {
              for (var l = 0; l < elements[0].dependency.length; l++) {
                elements[0].dependency[l].check();
              }
            }
            if (elements[0].tree) elements[0].tree.check(elements[0]);
          } else {
          }
        }
        break;
    }
  }
  // Ha van nem létező elem, akkor tovább próbálkozunk.
  if (failed != null && (this.failedRetries < this.failedMaxRetries)) {
    this.failedRetries++;
    window.setTimeout(function(self, cache){
      return function() {
        self.flushCache(cache);
      }
    }(this, failed), 100);
  } else {
    this.failedRetries = 0;
    //this.toggleForm();
  }
}
Cache.prototype.get = function () {
  var cache = JSON.stringify(this.getCache());
  if (cache != "{}") {
    this.setCookie(encodeURIComponent(cache));
  } else {
    eraseCookie(this.form.name);
  }
}
Cache.prototype.flush = function () {
  var cache = this.getCookie();
  if (cache != "null") {
    cache = JSON.parse(cache);
    //this.toggleForm();
    this.failedRetries = 0;
    this.flushCache(cache);
  }
}

function initCache() {
  for (var i = 0; i < document.forms.length; i++) {
    if (document.forms[i].className.match(/cacheable/)) {
      var cache = new Cache(document.forms[i]);
      cache.initCacheable();
    }
  }
}
//Event.observe(window, 'load', initCache);
// A Firefox átmeneti tárának megkerülése.
Event.observe(window, 'pageshow', function(e){
  if (e.persisted) initCache();
});
