/*
 * Sozi - An alternative presentation system
 *
 * Copyright (C) 2009  Guillaume Savaton
 *
 * This program 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.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

const SOZI_STEPS = 25;
const SOZI_TIME_STEP = 10;

function Sozi(root) {

   this._root = root;

   root.setAttribute("width", "100%");
   root.setAttribute("height", "100%");

   this._contentLayer = document.getElementById("content-layer");
   this._viewsLayer = document.getElementById("views-layer");
   this._views = this._viewsLayer.getElementsByTagName("rect");
   this._controls = document.getElementById("control-box");

   var that = this;

   document.getElementById("control-first").onclick = function(evt) {
      that.moveToFirst();
   }

   document.getElementById("control-last").onclick = function(evt) {
      that.moveToLast();
   }

   document.getElementById("control-previous").onclick = function(evt) {
      that.moveToPrevious();
   }

   document.getElementById("control-next").onclick = function(evt) {
      that.moveToNext();
   }

   this.moveToFirst();
}

Sozi.prototype = {
   setStep: function(index) {
      this._step = index;

      var initialMatrix = this._contentLayer.getCTM();

      var rect = this._views[index];
      var finalMatrix = rect.getCTM().inverse();
      finalMatrix.e -= rect.getAttribute("x");
      finalMatrix.f -= rect.getAttribute("y");

      var factor = Math.min(window.innerWidth / rect.getAttribute("width"),
                            window.innerHeight / rect.getAttribute("height"));

      finalMatrix.a *= factor;
      finalMatrix.b *= factor;
      finalMatrix.c *= factor;
      finalMatrix.d *= factor;
      finalMatrix.e *= factor;
      finalMatrix.f *= factor;

      var xoffset = (window.innerWidth - factor * rect.getAttribute("width")) / 2;
      var yoffset = (window.innerHeight - factor * rect.getAttribute("height")) / 2;

      if(xoffset > 0)
         finalMatrix.e += xoffset;
      if(yoffset > 0)
         finalMatrix.f += yoffset;

      finalMatrix = finalMatrix.multiply(initialMatrix);

      this.animate(initialMatrix, finalMatrix, 0, rect.getAttribute("class")=="transient");
   },

   animate: function(initialMatrix, finalMatrix, step, isTransient) {
      var matrix = this._root.createSVGMatrix();
      matrix.a = initialMatrix.a + (finalMatrix.a - initialMatrix.a) * step/SOZI_STEPS;
      matrix.b = initialMatrix.b + (finalMatrix.b - initialMatrix.b) * step/SOZI_STEPS;
      matrix.c = initialMatrix.c + (finalMatrix.c - initialMatrix.c) * step/SOZI_STEPS;
      matrix.d = initialMatrix.d + (finalMatrix.d - initialMatrix.d) * step/SOZI_STEPS;
      matrix.e = initialMatrix.e + (finalMatrix.e - initialMatrix.e) * step/SOZI_STEPS;
      matrix.f = initialMatrix.f + (finalMatrix.f - initialMatrix.f) * step/SOZI_STEPS;

      var transform = "matrix(" + matrix.a + " " +
                                  matrix.b + " " +
                                  matrix.c + " " +
                                  matrix.d + " " +
                                  matrix.e + " " +
                                  matrix.f + ")";

      this._contentLayer.setAttribute("transform", transform);
      this._viewsLayer.setAttribute("transform", transform);

      if(step < SOZI_STEPS) {
         var that = this;
         window.setTimeout(function() {
               that.animate(initialMatrix, finalMatrix, step+1, isTransient);
            }, SOZI_TIME_STEP);
      }
      else if(isTransient)
         this.moveToNext();
   },

   moveToFirst: function() {
      this.setStep(0);
   },

   moveToLast: function() {
      this.setStep(this._views.length-1);
   },

   moveToPrevious: function() {
      if(this._step > 0)
         this.setStep(this._step - 1);
   },

   moveToNext: function() {
      if(this._step < this._views.length-1)
         this.setStep(this._step + 1);
   },

}

function soziStart(evt) {
   var soziData = new Sozi(evt.target);
}

