/*
 * (c) Copyright 2006 Stephen Butterworth.
 * ALL RIGHTS RESERVED
 *
 * SIZEASY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SIZEASY SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 */

var defaultOpacity = 0.7;
var tan15 = 0.2679;
var cos45 = 0.707;
var defaultScale = 1.8

var maxVertDim = 220;
var maxHorDim = 165;

var maxFaceVertDim = 320;
var maxFaceHorDim = 385;

var originX = 211;
var originY = 236;

var onloads = new Array();

var firstResize = true;

//All external links (defined by being absolute urls) open a new window
function externalLinks() {
 if (!document.getElementsByTagName) return; 
 var anchors = document.getElementsByTagName("a");
 for (var i=0; i<anchors.length; i++) { 
   var anchor = anchors[i];
   if (anchor.getAttribute("href") 
       && anchor.getAttribute("href") != "/"
       && anchor.getAttribute("href").indexOf("/page/")== -1
       && anchor.getAttribute("href").indexOf("sizeasy")== -1)
   {
        anchor.target = "_blank";
   }
 }
}

onloads.push(externalLinks)

function tabChanged(ctrl, i){
    if($("filters") && ctrl.id == "tab-pane-1"){
	   setTimeout('$("filters").style.display = "block"', 20);
	}
	if(ctrl.id == "tab-pane-2"){
	   if(i>0){
	       cubeController.revaluateFacePositions(cubeController.projections[i-1]);
	   }
	}
}

var nowShowing = 'add_what'
function showAddOption(id){
    $(nowShowing).style.display = "none";
    $(id).style.display = "block";
    nowShowing = id;
}

function showDiv(id)
{
    $(id).style.visibility = "visible";
}

function restartGif(img){
	var imgName = img.src.toUpperCase();
	if (imgName.indexOf(".GIF")){
		img.src = img.src;
	}
}


function resized(){   
    //get origin coordinate deltas
    var oldX = cubeController.originX;
    var oldY = cubeController.originY;
    cubeController.findStartPos(true);
    var dX = cubeController.originX - oldX;
    var dY = cubeController.originY - oldY;
    
    //move cubes by deltas 
    cubeController.shuffleCubes(0, dX, dY, {duration:0});
}

function setBusy(busy){
    $("busy1").style.visibility = busy ? "visible" : "hidden";
    $("busy2").style.visibility = busy ? "visible" : "hidden";
    $("add1").disabled = busy;
    $("add2").disabled = busy;
    document.body.style.cursor = busy ? "wait" : "default";
    restartGif($("busy1"))
    restartGif($("busy2"));
}

window.onresize = resized;

function pageloaded(){
    for(var i=0; i<onloads.length; i++)
        onloads[i]();
}

function loaded(){
    cubeController.findStartPos();
    cubeController.initItems(startItems);
}

var Item = Class.create();
Item.prototype = {

    initialize: function(id, h, w, d, unit, preset, color, label){
    
            var size = new Size([h, w, d], unit);
            this.cube = new Cube(size, label, id,
                                    cubeController.colors.getColor(color),
                                    cubeController.originX,
                                    cubeController.originY,
                                    ('null' == preset) ? false : true,
                                    ('null' == preset) ? null : preset);
             cubeController.colors.colorNames[color] = false
             this.cube.initing = true;
    
    }
}

var Size = Class.create();
Size.prototype = {

    initialize: function(arg, unit){
        this.units = new Units();
        this.regExp = new RegExp("([0-9\.]+)[ \s]*([A-Za-z\"'^xX]*)"+
                          "[\s ]*[xX][ \s]*([0-9\.]+)[ \s]*"+
                          "([A-Za-z\"'^xX]*)[ \s]*[xX]"+
                          "[ \s]*([0-9\.]+)[ \s]*([A-Za-z\"']*)");
        
        
        if(null == unit){
             this.defaultReadUnit = this.units.allUnits['mm'];
             this.defaultDisplayUnit = this.units.allUnits['mm'];
        }
        else{
            var unitObj = this.units.getUnit(unit);
            this.defaultReadUnit = unitObj;
            this.defaultDisplayUnit = unitObj;
        }
              
        this.unit = this.defaultDisplayUnit;
        this.dimensions = new Array(3);
        this.valid = true;
        if(arg instanceof Array){
            for(var i=0; i<3; i++)
            {
                this.dimensions[i] = new Dimension(arg[i], this.unit);
            }
        }
        else{
            this.parse(arg);
        }
    },
    
    parse: function(str){
        var components = this.regExp.exec(str);
        if(null == components){
            //alert("Failed to read size, please check 'tips & tricks' for valid formats")
            $$(".size").each( function(item){ item.show() })
            setBusy(false);
            this.valid = false;
            return;
        }
        $$(".size").each( function(item){item.hide()} )
        var currentUnit = this.defaultReadUnit;
        for(var i=components.length-1, j=2; i>1; i-=2, j--){
            var unit = this.units.getUnit(components[i]);
            if(unit!=null)
                currentUnit = unit;
            this.dimensions[j] = new Dimension(parseFloat(components[i-1]), currentUnit);
        }
        this.unit = currentUnit;
    },
    
    getDimensionsInMM: function(){
        // call function on each dimension so we return array of 3 
        // numbers in the specified units, no units specified means default
        // to unit assumed when reading
        var mmDims = this.dimensions.collect(function(dim) {return dim.getAsMM();});
        return mmDims;
    },
    
    getDimensionsInOrigUnit: function(){
        var orig = this.dimensions.collect(function(dim) {return dim.value;});
        return orig;
    },
    
    toParam: function(){
        var dimsAsStr = this.dimensions.collect(function(dim) {return dim.value});
        return dimsAsStr.join('x') + this.dimensions[0].unit.getAbbrev();
    },
    
    toString: function(){
        // returns the dimensions as a total string each dimension consists
        // of a unit eg 24mm x 35cm x 98m. The data is kept in the units 
        // that were read in so basically this is just a normalised form
        // of what was initially read in.
        var dimsAsStr = this.dimensions.collect(function(dim) {return dim.toString()});
        return dimsAsStr.join(' x ');
    }
}

var Units = Class.create();
Units.prototype = {
    initialize: function() {
        
        this.allUnits = new Array();
        this.units = new Array();
        this.psuedos = new Array();
        
        this.addUnit("mm", 1,
            ["mm", "milli", "mills", "millimetres", "millimetre", "mils"]);
        
        this.addUnit("in", 25.4,
            ["in", "inches", "inch", "\"", "inche"]);
        
        this.addUnit("cm", 10,
            ["cm", "centimeter", "centimeters", "centimetre", "centimetres", "cent", "cents"]); 
            
        this.addUnit("m", 1000,
            ["m", "metres", "metre", "meters", "meters"]); 
            
        this.addUnit("ft", 304.8,
            ["ft", "feet", "foot", "'"]); 
                    
    },
    
    addUnit: function(abbrev, mmConv, psuedos){
        var newUnit = new Unit(abbrev, mmConv, psuedos);
        for(var i=0; i<psuedos.length; i++){
            this.psuedos[psuedos[i]] = newUnit;
        }
        //eval("this."+abbrev+"=newUnit");
        this.allUnits[abbrev] = newUnit;
    },
    
    getUnit: function(unitTxt){
        if(unitTxt == null || unitTxt.length==0)
            return null;
        else if(null != this.psuedos[unitTxt])
            return this.psuedos[unitTxt];
    }
    
}

var Unit = Class.create();
Unit.prototype = {
    initialize: function(abbrev, mmConv, psuedos) {
        this.abbrev = abbrev;
        this.psuedos = psuedos;
        this.mmConv = mmConv;
    },
    
    getAbbrev: function(){
        return this.abbrev;
    },
    
    hasPsuedo: function(candidate){
        return -1 != this.psuedos.indexOf(candidate);
    }
}

var Dimension = Class.create();
Dimension.prototype = {
    initialize: function(value, unit) {
        this.unit = unit;
        this.value = value;
    },
    
    getAsMM: function(){
        return this.unit.mmConv * this.value;
    },
    
    toString: function(){
        return this.value + this.unit.getAbbrev();
    }
}
    
var Preset = Class.create();
Preset.prototype = {
    initialize: function(id, title, h, w, d) {
    this.id = id;
    this.title = title;
    this.height = h;
    this.width = w;
    this.depth = d;
  }
}

var URL = Class.create();
URL.prototype = {

  initialize: function(base, paramsHash) {
    this.base = base;
    this.params = paramsHash;
  },
  
  toString: function()
  {
    var keys = $H(this.params).keys();
    var values = $H(this.params).values();
    var url = this.base+"?";
    for(var i=0; i<keys.length; i++)
    {
        if(values[i] instanceof Array)
        {
            for(var j=0; j<values[i].length; j++)
            {
                url += this.urlParamStr(keys[i]+"[]", values[i][j])
            }
        }
        else
        {
            url += this.urlParamStr(keys[i], values[i])
        }
    }
    return url.substr(0, url.length-1);
  },
  
  urlParamStr: function(name, value)
  {
    var url = name;
    url += "=";
    url += value;
    url += "&";
    return url
  }
}

function addAjax(initing, cubeQS) 
{
     if(!initing){
        //alert(absoluteRoot+"item/add")
        new Ajax.Request(imPathPrefix+"item/add", {method: 'post', parameters: cubeQS.substr(1,cubeQS.length-1)});
    }
}

var Cube = Class.create();
Cube.prototype = {
  initialize: function(size, label, id, color, oX, oY, isPreset, image) {
    
    this.size = size;
    dimensions = size.getDimensionsInMM();
    h = dimensions[0];
    w = dimensions[1];
    d = dimensions[2];
        
    this.actual_height = h;
    this.actual_width = w;
    this.actual_depth = d;
    
    this.height = h;
    this.width = Math.round(w * cos45); //account for angle of view
    this.depth = Math.round(d * cos45); //account for angle of view
    
    this.orig_height = this.height;
    this.orig_width = this.width;
    this.orig_depth = this.depth;
    
    dimensions_orig_units = size.getDimensionsInOrigUnit();
    this.actual_height_orig_units = dimensions_orig_units[0];
    this.actual_width_orig_units = dimensions_orig_units[1];
    this.actual_depth_orig_units = dimensions_orig_units[2];
    
    this.calcSizesAndPositions();
    this.isLoaded = false;
    this.id = id;
    this.label = label;
    this.opacity = 1;
    this.hidden = false;
    this.image = image;
    
    this.color = color;
    this.isPreset = isPreset;
    this.scaleFactor = defaultScale;
    this.oX = oX;
    this.oY = oY;
    
    this.top = 0;
    this.left = 0;
    
  },
  
  load: function(){
    this.insertFilter();
    this.insertCube();
    Sortable.create('filters',{tag: 'div', onChange: cubeController.pendingRearrange, onUpdate:cubeController.rearrange});
  },
  
  setZIndex: function(ind){
    $(this.id).style.zIndex = ind;
  },
  
  scale: function(factor){
  
    this.scaleFactor = factor;

    this.height = Math.round(this.orig_height * factor);
    this.width  = Math.round(this.orig_width * factor); //account for angle of view
    this.depth  = Math.round(this.orig_depth * factor); //account for angle of view
    
    this.calcSizesAndPositions();
       
  },
  
  calcSizesAndPositions: function(){
    //origin1 is furthest bottom corner
    this.origin1_x = this.width;
    this.origin1_y = this.height;
    
    //origin2 is furthest right corner at bottom
    this.origin2_x = (this.width + this.depth)
    this.origin2_y = (this.height + (tan15 * this.depth));
    
    this.im_width =  this.depth + this.width;
    this.im_height = Math.round(this.height + (tan15*this.width) + (tan15*this.depth));
    
    newTop = this.oY-this.height;
    newLeft = this.oX-this.width;
    if($(this.id))
    {
        this.moveCube(newLeft, newTop, {duration: 0});
        $(this.id).style.width = this.im_width;
        $(this.id).style.height = this.im_height;
        $("im"+this.id).width = this.im_width;
        $("im"+this.id).height = this.im_height;
    }
    else
    {
        this.top = newTop;
        this.left = newLeft;
    }
  },
  
  insertCube: function() {

    var cubeQS = this.getCubeQueryString();

    var cubeURL = imPathPrefix + "imagegen/cube" + cubeQS;
    var frontURL = imPathPrefix +  "imagegen/face" + cubeQS;
    var sideURL = imPathPrefix + "imagegen/face" + cubeQS;
    var topURL = imPathPrefix + "imagegen/face" + cubeQS;
    
    
    
    if(this.isPreset){
        frontURL+="&face=front";
        sideURL+="&face=side";
        topURL+="&face=top"
    }
    
    //cube HTML 
    var cubeHTML = '<div id="'+this.id+'" style="visibility:hidden;opacity:0;filter:alpha(opacity=0);position:absolute;top:0;left:0'
                    + '"><img id="im'+this.id+'" onload="cubeController.cubeLoaded(\''+this.id+'\')" alt="'+this.label+'" title="'+this.label+'" src="'+cubeURL
                    + '" height="'+Math.round(this.im_height)+'" width="'+Math.round(this.im_width)+'" ></img></div>';
    new Insertion.Bottom('cubeCanvas', cubeHTML)
    
    //front face HTML
    var frontHTML = '<div id="front_'+this.id+'" style="visibility:hidden;opacity:0;filter:alpha(opacity=0);position:absolute;top:0;left:0'
                    + '"><img id="im_front_'+this.id+'" onload="cubeController.faceLoaded(\''+this.id+'\',\'front\')" alt="'+this.label+'" title="'+this.label+'" src="'+frontURL
                    + '" height="'+this.actual_height+'" width="'+this.actual_width+'" ></img></div>';
    new Insertion.Bottom('frontCanvas', frontHTML)
    //side face HTML
    var sideHTML = '<div id="side_'+this.id+'" style="visibility:hidden;opacity:0;filter:alpha(opacity=0);position:absolute;top:0;left:0'
                    + '"><img id="im_side_'+this.id+'" onload="cubeController.faceLoaded(\''+this.id+'\',\'side\')" alt="'+this.label+'" title="'+this.label+'" src="'+sideURL
                    + '" height="'+this.actual_height+'" width="'+this.actual_depth+'" ></img></div>';
    new Insertion.Bottom('sideCanvas', sideHTML)
    //top face HTML
    var topHTML = '<div id="top_'+this.id+'" style="visibility:hidden;opacity:0;filter:alpha(opacity=0);position:absolute;top:0;left:0'
                    + '"><img id="im_top_'+this.id+'" onload="cubeController.faceLoaded(\''+this.id+'\',\'top\')" alt="'+this.label+'" title="'+this.label+'" src="'+topURL
                    + '" height="'+this.actual_height+'" width="'+this.actual_width+'" ></img></div>';
    new Insertion.Bottom('topCanvas', topHTML)
    
    window.setTimeout("addAjax("+this.initing+",'"+cubeQS+"')", 1000)
  }, 

  getCubeQueryString: function() {
    var params = {format:".png",
                  color: this.color ? this.color.toRGBArray(): "",
                  ref: this.image,
                  w:this.actual_width_orig_units,
                  d:this.actual_depth_orig_units,
                  h:this.actual_height_orig_units,
                  isPreset:this.isPreset,
                  scale:this.scaleFactor,
                  id:this.id,
                  unit:this.size.unit.getAbbrev(),
                  label:escape(this.label),
                  colName:this.color.name};

    url  = new URL("", params);
    return url.toString();
  },
  
  insertFilter: function() {
    forecolor = this.color.darken(0.5).toRGBStr();
    var filterHTML = '<div id="filter'+this.id+'" class="padie filter" style="visibility:hidden;opacity:0;filter:alpha(opacity=0)"><div style="height:32px;padding:2px;background-image:url(\''+imPathPrefix+'images/filter-'+this.color.name+'.jpg\');background-repeat: repeat-x"><a onmousedown="return false" href="javascript:cubeController.toggleFilter(\''+this.id+'\')"><img onmousedown="return false" border="0" class="filter-eye" alt="show/hide" title="show/hide" id="eye'+this.id+'" src="'+imPathPrefix+'images/eye.png" width="20px" height="15px"'+
                     '></img></a><div class="filter-title">'+this.label+'<br/><span class="filter-size">('+this.size.toString()+')</span></div><a href="javascript:cubeController.removeCube(\''+this.id+'\')"><img border="0" alt="delete" title="delete" width="15" height="14" class="filter-cross" src="'+imPathPrefix+'images/cross.png"></img></a>'+
                     '</div>';
    new Insertion.Bottom('filters', filterHTML);
  }, 
  
  setOpacity: function(opacity) {
    new Effect.Opacity(this.id, {to:opacity, duration:0});
  },
  
  moveCube: function(left, top, effectOptions) {
  
    new Effect.Move(this.id, {duration:0, x:this.left, y:this.top, mode: 'absolute'});
    this.top = top;
    this.left = left;
  },
  
  hide: function(){
    this.hidden = true;
    $(this.id).style.visibility = "hidden";
    $("front_"+this.id).style.visibility = "hidden";
    $("side_"+this.id).style.visibility = "hidden";
    $("top_"+this.id).style.visibility = "hidden";
    Effect.Fade(this.id, {to:0, duration: 0});
  },
  
  show: function(){
    this.hidden = false;
    if(!cubeController.hidden)
    {
        $(this.id).style.visibility = "visible";
    }
    $("front_"+this.id).style.visibility = "visible";
    $("side_"+this.id).style.visibility = "visible";
    $("top_"+this.id).style.visibility = "visible";
    Effect.Appear(this.id, {to: defaultOpacity, duration: 0});
  }
  
}

var Color = Class.create();
Color.prototype = {
  initialize: function(name, r, g, b) {
    this.name = name;
    this.red = r;
    this.green = g;
    this.blue = b;
  },
  
  lighten: function(factor)
  {
     var newrgb = new Array();
     var newred = Math.round(this.red + ((255-this.red) * factor));
     var newgreen = Math.round(this.green + ((255-this.green) * factor));
     var newblue = Math.round(this.blue + ((255-this.blue) * factor));
     return new Color("light"+this.name, newred, newgreen, newblue);
  },
  
  darken: function(factor)
  {
     var newrgb = new Array();
     var newred = Math.round(this.red * factor);
     var newgreen = Math.round(this.green * factor);
     var newblue = Math.round(this.blue * factor);
     return new Color("dark"+this.name, newred, newgreen, newblue);
  },

  toRGBStr: function()
  {
    return 'rgb('+this.red+','+this.green+','+this.blue+')';
  },
  
  toRGBArray: function(){
    return [this.red, this.green, this.blue];
  }
}

var Colors = Class.create();
Colors.prototype = {
  initialize: function() {
  
    this.colorNames = new Array();
    this.colors = new Array();
    
    this.addColor("purple", 143, 93, 179); 
    this.addColor("red", 241, 71, 71);
    this.addColor("orange", 240, 200, 38);
    this.addColor("blue", 67, 86, 144);
    this.addColor("green", 103, 204, 63);
    this.addColor("pink", 255, 87, 170);
    this.addColor("turquoise", 81, 255, 171);
    this.addColor("peach", 255, 191, 112);
    this.addColor("white", 255, 255, 255);
    this.colorNames["white"] = false; //not available - used by presets
    
  },
  
  addColor: function(name, r, g, b){
    this.colorNames[name] = true;
    this.colors[name] = new Color(name, r, g, b);
  },
  
  getAvailableColor: function() {
    var keys = $H(this.colorNames).keys();
    var values = $H(this.colorNames).values();
    for(var i=0; i<values.length; i++)
    {
        if(values[i])
        {
            this.colorNames[keys[i]] = false;
            return this.colors[keys[i]];
        }
    }
    return false;
  },
  
  getColor: function(name){
    return this.colors[name]
  },
  
  setAvailableColor: function(name){
    this.colorNames[name] = true;
  }
}

var realSrc;
var blankSrc = imPathPrefix + "images/blank.gif";
var isPrinting = false;

function fixImage(element) {
	// get src
	if(!document.all)
	   return;
	var src = element.src;

	// check for real change
	if (src == realSrc && (-1 != src.indexOf(".png"))) {
		element.src = blankSrc;
		return;
	}

	if ( ! new RegExp(blankSrc).test(src)) {
		// backup old src
		realSrc = src;
	}

	// test for png
	if (-1 != realSrc.indexOf(".png")) {
		// set blank image
		element.src = blankSrc;
		// set filter
		element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft." +
					"AlphaImageLoader(src='" + src + "',sizingMethod='scale')";
	}
	else {
		// remove filter
		element.runtimeStyle.filter = "";
	}
}     
              
var CubeController = Class.create();
CubeController.prototype = {
  initialize: function() {
    
    //origin1 is furthest bottom corner
    this.maxCubes = 5;
    this.cubesArray = new Array();
    this.cubesHash = new Array();
    this.uniqueIDCounter = 0;
    this.colors = new Colors();
    this.defaultLabel = "My Item"
    this.hidden = false;
    this.projections = ["front", "side", "top"];
    this.cubesInited = 0;
    this.permalink = "";

    this.originX = originX;
    this.originY = originY;
    
    this.scale = defaultScale;
    this.rearrangeID = null;
  },
  
  findStartPos: function(resize)
  {
     this.originX = originX;// + Element.findPosX("cubeCanvas");
     this.originY = originY;// + Element.findPosY("cubeCanvas");     
  },
  
  rearrange: function(div)
  {
      cubeController.hide();
      id = cubeController.rearrangeID;
      initialCubePos = id.substr(id.indexOf("_")+1);
      pos = cubeController.getCubeIndex(id.replace("filter",""));
      cubeController.rearrangeCube(pos, initialCubePos);
      cubeController.reEvalScale();
      cubeController.show();
      cubeController.comparisonChanged();
  },
  
  pendingRearrange: function(div)
  {
      cubeController.rearrangeID = div.id;
  },
  
  getCubeIndex: function(id)
  {
      for(var i=0; i<this.cubesArray.length; i++)
      {
        if(this.cubesArray[i].id == id)
            return i;
      }
  },
  
  positionCubes: function(duration){
      if(duration==null)
        duration = 0.5;
      var cubes = this.cubesArray;
      var nextX = this.originX;
      var nextY = this.originY;
      for(var i=0; i<cubes.length; i++)
      {
          if(!cubes[i].hidden)
          {
            var newLeft = nextX - cubes[i].width;
            var newTop = nextY - cubes[i].height;
            nextX += (cubes[i].origin2_x - cubes[i].origin1_x)
            nextY += (cubes[i].origin2_y - cubes[i].origin1_y)
            cubes[i].moveCube(newLeft, newTop, {duration: 0})
          }
          cubes[i].setZIndex(i+1);
      }
      this.shuffleCubes(0,0,0,{duration:0})
  },
  
  rearrangeCube: function(cubePos, initialCubePos)
  {
      //update cubesArray
      var newOrder = Sortable.serialize('filters');
      var arr = newOrder.split('filters[]=');
      for(var i=0; i<arr.length; i++)
      {
        if(arr[i].indexOf(initialCubePos) != -1)
            break;
      }
      newPos = i-1;
      var oldPos = cubePos;
      new Ajax.Request(imPathPrefix+"item/reorder", {method: 'get', parameters: "from="+oldPos+"&to="+newPos});
      var cube = this.cubesArray[oldPos]
      this.cubesArray.splice(oldPos,1);
      this.cubesArray.splice(newPos,0,cube);
      this.positionCubes(0);
      this.reorderFaces();
      
  },
  
  initialiseCube: function(id)
  {
     cubeController.hide();
     var cube = this.getCube(id);
     var lastVis = this.cubesArray[this.getLastVisibleCube()];
     new Effect.MoveBy(cube.id, this.originY-cube.height, this.originX-cube.width,{duration: 0}); 
     cube.show();
     $("filter" + id).style.visibility = "visible";
     new Effect.Appear("filter" + id, {to: 1, duration: 0.5});
     new Effect.Appear("filters", {to: 1, from: 1, duration: 0});
     
     if(!(this.cubesArray.length <= 1 || lastVis<0))
     {
        if(lastVis != null)
        {
            var newLeft = Math.round((lastVis.left + lastVis.im_width)-cube.width);
            var newTop = Math.round((lastVis.top + lastVis.origin2_y)-cube.height);
            cube.moveCube(newLeft, newTop, {duration:0});
        }
        cube.setZIndex(this.cubesArray.length);
     }
    
     
     this.reEvalScale();
     cubeController.show();     
     if(this.cubesArray.length==1)
     {
        this.shuffleCubes(0, 0, 0, {duration:0});
     }
  },
  
  handleIniting: function(){
    this.cubesInited++;
    if(this.cubesInited == startItems.length){
        for(var i=0; i<startItems.length; i++){
            startItems[i].cube.initing = false;
            this.cubeLoaded(startItems[i].cube.id);
        }
        $("loading").style.visibility = "hidden";
    }
  },
  
  cubeLoaded: function(id){

    var cube = this.getCube(id);
    
    
    if(document.all && !cube.isLoaded)
    {
      setTimeout(function() {cube.isLoaded = true;fixImage($(id).childNodes[0]);}, 50);
      return;
    }
    
        
    if(cube.initing){
        this.handleIniting();
        return;
    }

    this.initialiseCube(id);
    setBusy(false);
  },
  
  scaleFaces: function(projection){
    //get max dims
    var width, height, maxHeight=0, maxWidth = 0;
    var dims = new Array();
    var visiCubes = this.getVisibleCubes();
    for(var i=0; i<visiCubes.length; i++){
        dims[i] = new Object();
        if(projection == "front"){   
            dims[i].height = visiCubes[i].actual_height;
            dims[i].width = visiCubes[i].actual_width;
        }
        else if(projection == "side"){   
            dims[i].height = visiCubes[i].actual_height;
            dims[i].width = visiCubes[i].actual_depth;
        }
        else if(projection == "top"){   
            dims[i].height = visiCubes[i].actual_depth;
            dims[i].width = visiCubes[i].actual_width;
        }
        maxHeight = Math.max(maxHeight, dims[i].height);
        maxWidth  = Math.max(maxWidth, dims[i].width);
    }
    var scaleFactor = Math.min(maxFaceHorDim/maxWidth, maxFaceVertDim/maxHeight);
    for(var i=0; i<visiCubes.length; i++){
        dims[i].height = Math.ceil(dims[i].height * scaleFactor);
        dims[i].width = Math.ceil(dims[i].width * scaleFactor);
        $("im_"+projection+"_"+visiCubes[i].id).height = dims[i].height;
        $("im_"+projection+"_"+visiCubes[i].id).width = dims[i].width;
        $(projection+"_"+visiCubes[i].id).style.height = dims[i].height;
        $(projection+"_"+visiCubes[i].id).style.width = dims[i].width;
         
        //$(projection+"_"+this.cubesArray[i].id).style.backgroundColor = "red";
    }
    dims.maxHeight = maxHeight * scaleFactor;
    dims.maxWidth = maxWidth * scaleFactor;
    return dims;
  },
  
  positionFaces: function(projection, dims){
    var topOffset  = 10 + (maxFaceVertDim-dims.maxHeight)/2;
    var leftOffset = 15 + (maxFaceHorDim-dims.maxWidth)/2;
    var visiCubes = this.getVisibleCubes();
    for(var i=0; i<visiCubes.length; i++){
        var errorOffsetY = $("im_"+projection+"_"+visiCubes[i].id).offsetTop;
        var errorOffsetX = $("im_"+projection+"_"+visiCubes[i].id).offsetLeft;
        new Effect.Move(projection+"_"+visiCubes[i].id, {y: (dims.maxHeight-dims[i].height)+topOffset-errorOffsetY, x:(dims.maxWidth-dims[i].width)+leftOffset-errorOffsetX, duration: 0, mode: 'absolute'}); 
        $(projection+"_"+visiCubes[i].id).style.zIndex = i;
    }
  },
  
  displayFaces: function(projection){
    var visiCubes = this.getVisibleCubes();
    for(var i=0; i<visiCubes.length; i++){
        $(projection+"_"+visiCubes[i].id).style.visibility = "visible";
        Effect.Appear(projection+"_"+visiCubes[i].id, {to: defaultOpacity, duration: 0});
    }
  },
  
  faceLoaded: function(id, projection){

    var thisCube = this.getCube(id);
    if(!eval('thisCube.'+projection+'Loaded'))
    {
        eval('thisCube.'+projection+'Loaded=true;')
        //scale
        var dims = this.scaleFaces(projection);
        //position (inc. z-indexes)
        this.positionFaces(projection, dims);
        //display faces
        this.displayFaces(projection);
        if(thisCube.isPreset)
            fixImage($("im_"+projection+"_"+id));
     }
  },
  
  revaluateFacePositions: function(projection){
    if(projection == null){
        for(var i=0; i<this.projections.length; i++){
            this.revaluateFacePositions(this.projections[i]);
        }
        return;
    }
    var dims = this.scaleFaces(projection);
    //position (inc. z-indexes)
    this.positionFaces(projection, dims);
  },
  
  reorderFaces: function(){
    for(var i=0; i<this.cubesArray.length; i++){
        $("front_"+this.cubesArray[i].id).style.zIndex = i;
        $("side_"+this.cubesArray[i].id).style.zIndex = i;
        $("top_"+this.cubesArray[i].id).style.zIndex = i;
    }
  },

  getLastVisibleCube: function(startpos)
  {
    var lastVisible;
    if(startpos == null)
        startpos = this.cubesArray.length-2;
    for(var i=startpos; i>=0 && this.cubesArray[i].hidden; i--){}
    return Math.max(-1,i);
  },
  
  getVisibleCubes: function(cube){
    var visibleArray = new Array();
    for(var i=0; i<this.cubesArray.length; i++){
        if(!this.cubesArray[i].hidden || this.cubesArray[i]==cube)
            visibleArray.push(this.cubesArray[i]);
    }
    return visibleArray;
  } ,
  
  isAvailableLabel: function(label){
    for(var i=0; i<this.cubesArray.length; i++){
        if(label == this.cubesArray[i].label){
            return false;
        }
    }
    return true;
  },
  
  getAvailableLabel: function(label){
    if(label == "")
        label = this.defaultLabel;
    
    if(this.isAvailableLabel(label)){
        return label;
    }
    else{
        for(var j=0; j<this.cubesArray.length; j++){
            var proposedLabel = label+" ("+(j+1)+")";
            if(this.isAvailableLabel(proposedLabel))
                return proposedLabel;
        }
    }
    return label;  
  },
  
  scaleAll: function(factor){
    this.scale = factor;
    for(var i=0; i<this.cubesArray.length; i++)
    {
        this.cubesArray[i].scale(factor);
    }
    this.positionCubes(0);
  },
  
  isMax: function(){
    if(this.cubesArray.length == this.maxCubes)
    {
        //alert("You can only have "+this.maxCubes+" items in your comparison. To add this item switch to the \"my items\" tab and delete an item then try adding again." )
        $$(".count").each( function(item){item.show()} )
        return true;
    }
    else
    {
        return false;
    }
  },
  
  initItems: function(items){
    for(var i=0; i<items.length; i++){
        var cube = items[i].cube;
        cube.scale(this.scale);
        this.cubesArray.push(cube);
        this.cubesHash[cube.id] = cube;
        //this.uniqueIDCounter++;
        cube.load();
    }
    this.comparisonChanged();
  },
  
  comparisonChanged: function(){
/*
    var permalink = permalink_base;
    var sep = "?"
    this.cubesArray.each( function(cube){
       permalink += sep;
       sep = "&";
	   if(cube.isPreset)
         permalink += "p[]="+cube.image+"&t[]=p";
       else
         permalink += "d[]="+cube.size.toParam()+"&n[]="+cube.label+"&t[]=i";	
	});
	
    wrappedLink = this.addNewLines(permalink, 50);
    $("permalink").innerHTML = "<a href='"+permalink+"'>"+wrappedLink+"</a>";
    
*/
//    $("shortlink").innerHTML = "";
  },
  
  addNewLines: function(text, break_at){
    
    var newStr = "";
    for(i=1; i<text.length/break_at; i++)
    {
        newStr += text.substr((i-1)*break_at, break_at);
        newStr += "<br>";
    }
    newStr += text.substr((i-1)*break_at, break_at);
    return newStr;
    
  },
  
  addCube: function(label, dims){

    if(this.isMax()) return;
    
    setBusy(true);
    
    var size = new Size(dims);
        
    if(!size.valid)
        return;
    
    //Create new cube object
    var name = this.getAvailableLabel(label);
    var cube = new Cube(size, name, "cube_" + this.uniqueIDCounter,
                        this.colors.getAvailableColor(), this.originX,
                        this.originY, false, null);
    
    cube.scale(this.scale);
    
    this.cubesArray.push(cube);
    this.cubesHash[cube.id] = cube;
    this.uniqueIDCounter++;
    cube.load();
    this.comparisonChanged();
    
  },

  sortNumber: function(a, b){
    return a - b
  },
  
  removeCube: function(id){
    
    new Ajax.Request(imPathPrefix+"item/remove", {method: 'get', parameters: "id="+id});
    
    var cube = this.getCube(id);
    if(!cube.hidden)
    {
        this.toggleFilter(id)
    }
    new Effect.Fade("filter" + id, {duration: 0.5});

    this.cubesArray = this.cubesArray.without(cube);
    
	if (typeof(this.cubesHash[id]) != 'undefined')
	{
		this.length--;
		delete this.cubesHash[id];
	}
		
    this.colors.setAvailableColor(cube.color.name);
    
    setTimeout(function() {Element.remove(id);Element.remove("filter"+id)}, 500);
    Element.remove("front_"+id);
    Element.remove("side_"+id);
    Element.remove("top_"+id);
    $$(".count").each( function(item){item.hide()} )
    this.comparisonChanged();
  },
  
  getCube: function(id){
    return this.cubesHash[id];
  },
  
  addPreset: function(){
  
    if(this.isMax()) return;
    
    var preset = presets[$F("presets")];
    setBusy(true)
    
    var cube = new Cube(new Size([preset.height, preset.width, preset.depth]), preset.title,
                        preset.id + "_" + this.uniqueIDCounter,
                        this.colors.getAvailableColor(), this.originX, this.originY, true, preset.id);
    cube.scale(this.scale);
    this.uniqueIDCounter++;
    this.cubesArray.push(cube);
    this.cubesHash[cube.id] = cube;
    cube.load(); 
    this.comparisonChanged();
  },
  
  toggleFilter: function(id){
    
    cubeController.hide();
    var cube = this.getCube(id);
    var fromInd = this.cubesArray.indexOf(cube)+1;
    show = cube.hidden;
    
    if(show)
    {
        this.reEvalScale(cube);
        this.shuffleCubes(fromInd, cube.origin2_x - cube.origin1_x, cube.origin2_y - cube.origin1_y, {duration:0});
        fromInd  = this.getLastVisibleCube(fromInd-1);
        if(fromInd<0)
        {
            xOrig = this.originX;
            yOrig = this.originY;
        }
        else
        {
            xOrig = this.cubesArray[fromInd].origin2_x+this.cubesArray[fromInd].left
            yOrig = this.cubesArray[fromInd].origin2_y+this.cubesArray[fromInd].top
        }
        newX = xOrig-cube.width;
        newY = yOrig-cube.height;
        cube.show();
        cube.moveCube(newX, newY,{duration:0})
        Effect.Fade("filter"+cube.id, {to:1, duration: 0.5});
        $("eye"+id).src = imPathPrefix+"images/eye.png";
    }
    else //hide
    {
        cube.hide();
        this.shuffleCubes(fromInd, dx = cube.origin1_x - cube.origin2_x, dy = cube.origin1_y - cube.origin2_y, {duration: 0});
        Effect.Fade("filter"+cube.id, {to:0.3, duration: 0.5});
        $("eye"+id).src = imPathPrefix+"images/eye-no.png";
    }
    cubeController.reEvalScale();
    cubeController.revaluateFacePositions();
    cubeController.show();
  },

  shuffleCubes: function(ind, dx, dy, effectOptions){
    for(var i=ind; i<this.cubesArray.length; i++)
    {
        var cube = this.cubesArray[i];
        cube.moveCube(cube.left+dx, cube.top+dy, effectOptions);
    }
  },
  
  reEvalScale: function(cube){
    var visCubes = cubeController.getVisibleCubes(cube);
    if(visCubes.length==0)
        return;
    var maxRight = 0; var maxLeft = 0; var maxTop=0;
    for(var i=0; i<visCubes.length; i++)
    {
        maxRight = Math.max(maxRight, visCubes[i].left + visCubes[i].im_width - cubeController.originX);
        maxLeft = Math.max(maxLeft, cubeController.originX - visCubes[i].left);
        maxTop = Math.max(maxTop, cubeController.originY - visCubes[i].top);
    }
    var max = [maxRight,maxLeft,maxTop].max();
    if(max == maxRight || max == maxLeft)
        maxDim = maxHorDim;
    else
        maxDim = maxVertDim;
    var newScale = cubeController.scale * (maxDim/max);
    cubeController.scaleAll(newScale);
  },
  
  hide: function(delayed){
    this.hidden = true;
    var visCubes = cubeController.getVisibleCubes();
    for(var i=0; i<visCubes.length; i++)
    {
        $(visCubes[i].id).style.visibility="hidden";
        //Effect.Fade(visCubes[i].id, {duration: 0.3, to: 0})
    }
  },
  
  show: function(delayed){
    this.hidden = false;
    if(delayed == null)
    {
        setTimeout("cubeController.show(true)", 50);
        return;
    }
    var visCubes = cubeController.getVisibleCubes();
    for(var i=0; i<visCubes.length; i++)
    {
        $(visCubes[i].id).style.visibility="visible";
        $(visCubes[i].id).style.display="block";
        new Effect.Appear(visCubes[i].id, {duration: 0, from: defaultOpacity, to: defaultOpacity})
    }
    
  }
}

var cubeController = new CubeController();
