var Game = Class.create();
Game.prototype = {
  initialize: function() {
    this.online = false;
    this.highscores = null;
  },

  construct: function(stats) {
    this.stats = stats;
    field = new Field(stats);
    field.construct();
    field.createElement();
    this.onResize();
    field.div.style.visibility = "visible";
    Event.observe(window, "resize", this.onResize.bind(this));
    this.reset();
    var to = Prototype.Browser.Opera ? 0.99 : 1;
    new Effect.Appear(field.div, {from: 0, to: to});
  },
  
  reset: function() {
    this.running = false;
    this.started = false;
    this.stopped = false;
    this.gameTime = 0;
    field.reset();
    field.generate();
    game.hideCurtain();
    this.updateTime();
    this.updateStatusBar();
    this.highscores = null;
    this.waitingForHighscores = false;
    this.onlineHighscore = false;
  },

  start: function() {
    this.startTime = new Date().getTime();
    this.updateTimeTimeout = setInterval(this.updateTime.bind(this), 1000);
    this.running = true;
    this.started = true;
    this.updateTime();
  },

  onResize: function() {
    var w = window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth);
    var h = window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight);
    var w2 = field.tileWidth * field.width / 2;
    var topbary = $("top") ? 100 : 20;
    field.div.setStyle({
      left: w / 2 - w2,
	  top: topbary + 65
	  });
    var pos = Position.cumulativeOffset(field.div);
    $("bottom").setStyle({top: pos[1] + field.tileHeight * field.height + 20, left: w / 2 - 185});
    var elm = $("curtain");
    elm.setStyle({
      top: pos[1],
	  left: pos[0],
	  width: field.div.getWidth(),
	  height: field.div.getHeight()
	  });
  },

  gameOver: function(won) {
    scheduleReport(null);
    this.running = false;
    this.stopped = true;
    this.gameTime = parseInt(timeSince(this.startTime) / 1000);
    this.won = won;
    new Effect.Shake(field.div, { duration: 0.5 });
    this.showCurtain();
  },

  showCurtain: function() {
    scheduleReport(null); // just in case
    if (this.waitingForHighscores) return;
    if (this.online && !this.highscores) {
      this.waitingForHighscores = true;
      return;
    }
    stopReporting();
    var elm = $("curtain");
    var pos = Position.cumulativeOffset(field.div);
    elm.setStyle({
      top: pos[1],
	  left: pos[0],
	  width: field.div.getWidth(),
	  height: field.div.getHeight()
	  });
    elm.style.visibility = "visible";
    var div = $("highscores");
    div.innerHTML = "";
    div.setStyle({width: field.div.getWidth(), height: field.div.getHeight() - 150, left: 0});
    $("restartactions").setStyle({visibility: "hidden"});
    var newhs = false;
    if (!game.online) {
      this.loadLocalHighscores();
      newhs = this.isHighscore(this.gameTime);
      if (newhs) this.insertHighscore(this.gameTime, null);
    }
    else {
      newhs = !!this.onlineHighscore;
    }
    $("highscoreslbl").innerHTML = strings[newhs ? "newhighscore" : "highscores"];
    new Effect.Appear(elm, {from: 0.0, to: 0.6, afterFinish: (this.onlineHighscore ? this.showNameInput.bind(this) : this.showHighscores.bind(this))});
  },

  showNameInput: function() {
    var div = $("nameinput");
    div.setStyle({visibility: "visible", display: "block", opacity: 0});
    n = getCookie("sd-name");
    if (!n) n = getCookie("name");
    $("name").value = n ? n : "";
    $("name").focus();
    if (Prototype.Browser.Gecko)
      div.setStyle({opacity: 1});
    else
      new Effect.Appear(div);
  },

  submitHighscoreName: function(name) {
    if (name.length > 12) name = name.substr(0, 12);
    this.insertHighscore(this.gameTime, name);
    new Effect.Fade($("nameinput"), {afterFinish: this.showHighscores.bind(this)});
    setCookie("sd-name", name);
    if (!getCookie("name")) setCookie("name", name);
  },

  showHighscores: function() {
    $("nameinput").setStyle({visibility: "hidden", display: "none"});
    var div = $("highscores");
    var pos = Position.positionedOffset(div);
    for (var i = 0; (h = this.highscores[i]) && i < this.stats.highscores; ++i) {
      var hs = $(document.createElement("div"));
      hs.addClassName("highscore");
      hs.setStyle({top: field.div.getHeight()});
      hs.innerHTML = (h[3] ? "<em>" : "") +
	formatSeconds(h[0]) + " " +
	(h[1] ? h[1] : "") + " " +
	'<small>' + formatAgo(h[2]) + '</small>' +
	(h[3] ? "</em>" : "");
      div.appendChild(hs);
      var offy = Prototype.Browser.IE ? 5 : 10 + pos[1];
      new Effect.Move(hs, {duration: 1 + 0.5 * i, y: offy + i * 25, mode: "absolute"});
    }
    var fn = function() {
      var elm = $("restartactions");
      elm.setStyle({opacity: 0, visibility: "visible"});
      new Effect.Appear(elm);
    }
    setTimeout(fn, 500 * this.highscores.length);
  },

  hideCurtain: function() {
    var elm = $("curtain");
    new Effect.Fade(elm);
  },

  updateTime: function() {
    if (!this.started) {
      $("time").innerHTML = "";
      return;
    }
    else if (!this.running) {
      clearTimeout(this.updateTimeTimeout);
      if (this.gameTime)
	$("time").innerHTML = "<b>" + formatSeconds(this.gameTime) + "</b>";
      else
	$("time").innerHTML = "<b>" + $("time").innerHTML + "</b>";
      return;
    }
    var time = parseInt(timeSince(this.startTime) / 1000);
    $("time").innerHTML = formatSeconds(time);
    if (time >= 6039) this.gameOver(false);
  },

  updateStatusBar: function() {
  },

  destruct: function() {
    field.removeElements();
    $("curtain").setStyle({opacity: 0, visibility: "hidden"});
    $("field").setStyle({opacity: 0, visibility: "hidden"});
  },

  loadLocalHighscores: function() {
    this.highscores = $A();
    var c = getCookie("sd-hs-" + this.stats.level);
    if (!c) return;
    var s = $A(c.split("|"));
    this.highscores = s.collect(function(x) {
				  var y = x.split("@");
				  return [parseInt(y[0]), null, parseInt(timeSince(parseInt(y[1]) * 1000) / 1000)];
				});
  },
  
  isHighscore: function(secs) {
    return this.highscores.length < this.stats.highscores || secs <= this.highscores[this.highscores.length - 1][0];
  },

  insertHighscore: function(secs, name) {
    if (this.highscores.length == 0) {
      this.highscores = $A([[secs, name, 0, true]]);
      return;
    }
    if (this.highscores.length < this.stats.highscores &&
	secs > this.highscores.last()[0] && secs) {
      this.highscores.push([secs, name, 0, true]);
      return;
    }
    var ary = $A();
    for (var i = 0; (h = this.highscores[i]) && i < this.stats.highscores; ++i) {
      if (secs <= h[0] && secs) {
	ary.push([secs, name, 0, true]); secs = null;
      }
      if (ary.length < this.stats.highscores)
	ary.push(h);
    }
    this.highscores = ary;
  },

  saveLocalHighscores: function() {
    var s = this.highscores.map(function(h) {
				  var t = getTimeSecs() + h[2];
				  return h[0] + "@" + t;
				}).join("|");
    setCookie("sd-hs-" + this.stats.level, s);
  },

  goOffline: function() {
    this.online = false;
  },

  goOnline: function() {
    this.online = true;
  },

  highscoresReceived: function(hs, newhs) {
    this.highscores = $A(hs);
    this.onlineHighscore = newhs;
    if (this.waitingForHighscores) {
      this.waitingForHighscores = false;
      this.showCurtain();
    }
  }
};

