function memory(w, h, id)
{
  this.pieces = [];
  this.uncovered = {'p1':false,'p2':false};
  this.id = id;
  this.w = w;
  this.h = h;
  this.timer = null;
  this.seconds = 0;
  this.count = 0;
  this.found = 0;
  this.texts = {'success':{},'failure':''};
  var c = (w * h);
  var n = (c / 2);
  for (i = 0; i < c; i++) {
    this.pieces[i] = {'id':i,'mapping':(i % n) + 1,'visible':false,'object':null,'hint':'','cover':'','front':'','param':[]};
  }
	var host = window.location.host;
	if (host.lastIndexOf("gmx") != -1) {
		this.statichost = "//static.gmx.net/current/de";
	} else if (host.lastIndexOf("web") != -1) {
		this.statichost = "//static.web.de/current/de";
	} else if (host.lastIndexOf("1und1") != -1) {
		this.statichost = "//static.1und1.de/current/de";
	}
}
memory.prototype.reStart = function()
{
  if ($ui('#' + this.id + '-solved')) {
    $ui('#' + this.id + '-solved').style.display = 'none';
  }
  for (var i = 0; i < this.pieces.length; i++) {
    this.pieces[i].visible = false;
  }
  this.uncovered = {'p1':false,'p2':false};
  this.timer = null;
  this.seconds = 0;
  this.count = 0;
  this.found = 0;
  this.fillField();
}
memory.prototype.setPieces = function(data)
{
  var img;
  for (var i = 0; i < data.length; i++) {
    this.pieces[i]['front'] = data[i]['front'];
    this.pieces[i]['hint'] = data[i]['hint'];
    this.pieces[i]['mapping'] = data[i]['mapping'];
  }
}
memory.prototype.setCovers = function(covers)
{
  var i,img;
  if (typeof covers == 'string') {
    img = new Image();
    img.src = covers;
    for (i = 0; i < this.pieces.length; i++) {
      this.pieces[i]['cover'] = covers;
    }
  } else {
    for (i = 0; i < covers.length; i++) {
      img = new Image();
      img.src = covers;
      this.pieces[i]['cover'] = covers[i];
    }
  }
}
memory.prototype.setTexts = function(failure, texts)
{
  this.texts['failure'] = failure;
  this.texts['success'] = texts;
}
memory.prototype.shufflePieces = function()
{
  for (var j,x,i = this.pieces.length; i; j = parseInt(Math.random() * i),x = this.pieces[--i],this.pieces[i] = this.pieces[j],this.pieces[j] = x);
}
memory.prototype.fillField = function()
{
  var me = this;
  var c = 0;
  var x;
  var y;
  var d,e;
  var parent = $ui('#' + this.id + '-field');
  function _newClosure(num, cb) {
    return function() {
      cb(num);
    }
  }
  this.shufflePieces();
  for (y = 0; y < this.h; y++) {
    for (x = 0; x < this.w; x++) {
      if (this.pieces[c]['object'] == null) {
        d = document.createElement('div');
        d.style.cssFloat = 'left';
        d.style.styleFloat = 'left';
        d.style.margin = '0 1px 2px 0';
        d.style.padding = '0';
        d.style.width = '114px';
        d.style.height = '114px';
        d.style.background = 'url(' + this.statichost + '/images/common/memory/dropshadow.gif)';
        e = document.createElement('img');
        e.setAttribute('alt', this.pieces[c]['mapping']);
        e.style.margin = '0';
        e.style.padding = '0';
        e.style.width = '110px';
        e.style.height = '110px';
        e.style.cursor = 'pointer';
        d.appendChild(e);
        parent.append(d);
        this.pieces[c]['object'] = e;
      }
      this.pieces[c]['object'].src = this.pieces[c]['cover'];
      this.pieces[c]['object'].onclick = _newClosure(this.pieces[c], function(piece) {
        if (me.unCover(piece)) {
          me.onClick();
        }
      });
      ++c;
    }
  }
}
memory.prototype.unCover = function(piece)
{
  var me = this;
  if (piece['visible'] || this.uncovered['p2']) {
    return false;
  }
  if (!this.uncovered['p1']) {
    this.uncovered['p1'] = piece;
    this.uncovered['p1']['visible'] = true;
  } else {
    this.uncovered['p2'] = piece;
    this.uncovered['p2']['visible'] = true;
  }
  piece['object'].src = piece['front'];
  if (this.uncovered['p2']) {
    if ($ui('#' + this.id + '-hint')) {
      htmlTilNow = $ui('#' + this.id + '-hint').html();
	  $ui('#' + this.id + '-hint').html(htmlTilNow + ' + ' + piece['hint']);
    }
    if ($ui('#' + this.id + '-desc-short')) {
        htmlTilNow = $ui('#' + this.id + '-desc-short').html();
		$ui('#' + this.id + '-desc-short').html(htmlTilNow + ' + ' + piece['hint']);
    }
    if (this.uncovered['p1']['mapping'] != this.uncovered['p2']['mapping']) {
      this.failure();
    } else {
      this.uncovered['p1'] = false;
      this.uncovered['p2'] = false;
      ++this.found;
      this.success(piece);
    }
  } else {
    if (this.count == 0 && $ui('#' + this.id + '-timer')) {
      this.timer = window.setInterval(function() {
        ++me.seconds;
        var min = parseInt(me.seconds / 60);
        var sec = (me.seconds % 60);
        $ui('#' + me.id + '-timer').html('' + min + ':' + (sec > 9 ? '' : '0') + sec);
        me.onInterval(me.seconds);
      }, 1000);
    }
    ++this.count;
    if ($ui('#' + this.id + '-counter')) {
      $ui('#' + this.id + '-counter').html(this.count);
    }
    if ($ui('#' + this.id + '-hint')) {
      $ui('#' + this.id + '-hint').html(piece['hint']);
    }
    if ($ui('#' + this.id + '-desc-short')) {
      $ui('#' + this.id + '-desc-short').html(piece['hint']);
    }
    if ($ui('#' + this.id + '-desc-long')) {
      $ui('#' + this.id + '-desc-long').html('');
    }
  }
  return true;
}
memory.prototype.failure = function()
{
  var me = this;
  window.setTimeout(function() {
    me.coverPieces();
  }, 1000);
  if ($ui('#' + this.id + '-desc-long')) {
    $ui('#' + this.id + '-desc-long').html('<h1 style="background: url(' + this.statichost + '/images/common/icon-no-2.gif) left center no-repeat; padding-left: 22px; margin-bottom: 15px; font-weight: bold; color: #aa0000;">' + 'Falsch!</h1>' + '<p>' + this.texts['failure'] + '</p>');
  }
  this.onFailure();
}
memory.prototype.success = function(piece)
{
  if ($ui('#' + this.id + '-desc-long') && this.texts['success'] && this.texts['success'][piece['mapping']]) {
    $ui('#' + this.id + '-desc-long').html('<h1 style="background: url(' + this.statichost + '/images/common/icon-yes-2.gif) left center no-repeat; padding-left: 22px; margin-bottom: 15px; font-weight: bold; color: #00aa00;">' + 'Richtig!</h1>' + '<p>' + this.texts['success'][piece['mapping']] + '</p>');
  }
  this.onSuccess(piece['mapping']);
  if (this.found == (this.pieces.length / 2) && this.timer) {
    window.clearInterval(this.timer);
    if ($ui('#' + this.id + '-solved')) {
      $ui('#' + this.id + '-solved').css("display","block");
    }
    this.onSolved(piece['mapping']);
  }
}
memory.prototype.onInterval = function()
{
}
memory.prototype.onClick = function(param)
{
}
memory.prototype.onSolved = function()
{
}
memory.prototype.onFailure = function()
{
}
memory.prototype.onSuccess = function(mapid)
{
}
memory.prototype.coverPieces = function()
{
  this.uncovered['p1']['object'].src = this.uncovered['p1']['cover'];
  this.uncovered['p2']['object'].src = this.uncovered['p2']['cover'];
  this.uncovered['p1']['visible'] = false;
  this.uncovered['p2']['visible'] = false;
  this.uncovered['p1'] = false;
  this.uncovered['p2'] = false;
  if ($ui('#' + this.id + '-hint')) {
    $ui('#' + this.id + '-hint').html('');
  }
  if ($ui('#' + this.id + '-desc-short')) {
    $ui('#' + this.id + '-desc-short').html('');
  }
  if ($ui('#' + this.id + '-desc-long')) {
    $ui('#' + this.id + '-desc-long').html('');
  }
}