document.write("<style>.project{ opacity: 1 }</style>");

window.addEvent('domready', function() {
//  startup();
  makeTagMap();
  writeTagMap();
  
  writeZoomControls();
  Zoom.zoom_to_fit();
  Projects.initialiseProjects();
});

function writeZoomControls(){
  var zoomControls = ""; // "<h2 style='float: left; height: 20px; margin: 0; padding: 0; font-size: 18px; margin-top: 2px; padding-right: 10px;'>Zoom</h2>";
  zoomControls += "<img src='images/zoom_out.png' onclick='Zoom.zoom_out()' style='float: left; margin-top: 4px; cursor: pointer;'/>";
  for(var i=6; i<20; i+=2){ zoomControls += "<span id='zoom_bar_"+i+"' onclick='Zoom.zoom_to("+i+");' style=' width: 3px; height:  "+(i)+"px; margin-top: "+(20-i)+"px; display: block; float: left; border-right: 4px solid #999999; cursor: pointer;'></span>"; }
  zoomControls += "<img src='images/zoom_in.png' onclick='Zoom.zoom_in()' style='float: left;  margin-top: 4px; margin-left: 6px; cursor: pointer;'/>";
  $('zoomControls').innerHTML = zoomControls;
}

var Zoom = (function(){
  var zoom = 18;

  return {
    zoom_in : function(){
      this.zoom_to(zoom+2);
    },
    
    zoom_to : function(z){
      var old_zoom = zoom;
      zoom = z;
      if($('zoom_bar_'+old_zoom)) { $('zoom_bar_'+old_zoom).style.borderColor = '#999999'; }
      if($('zoom_bar_'+zoom)) { $('zoom_bar_'+zoom).style.borderColor = '#000'; }
      $('projects').set('tween', {duration : 500});
      $('projects').tween('font-size', zoom);
    },
    
    zoom_out : function(){
      this.zoom_to(zoom-2);
    },
    
    zoom_to_fit : function(){
      var fit = 12; //TODO: Calculate fit
      this.zoom_to(fit);
    },
    currentZoom : function(){
      return zoom;
    }
  }

})();

function zoom(){
  $('projects').set('tween', {duration : 3000});
  $('projects').tween('font-size', [18, 10]);
}

Array.prototype.difference = function(arr2){
  return this.filter(function(val){ return !arr2.contains(val); });
}

Array.prototype.intersection = function(arr2){
  return this.filter(function(val){ return arr2.contains(val); });
}

//if(!Array.prototype.reduce){
  Array.prototype.reduce = function(fn){
    if(this.length > 1){    
        var val;
        var first;
        this.each(function(next){
          if(!first){
            val = fn(next);
          }else{
            val = fn(first, next);
          }
          first = val;
        });
        return val;
    }
    if(this.length == 1){
      return fn(this[0]);
    }
  }
//}else{

//}


function startup(){
  var chain = new Chain();
  $each($$('.project'), function(el){
    chain.chain(function(){
      var fx = new Fx.Morph(el, {property : 'opacity', duration : 400});
      fx.addEvent('complete', function(){ chain.callChain() } );
      fx.set( { 'opacity' : 0} );    
      fx.start( {'opacity' : 0.8} );    
    });
  });
  chain.callChain();
}

function Tag(tagEl){

  function tagName(){
    return tagEl.innerHTML;
  }
  
  this.onmouseover = function(){
     tagEl.toggleClass('highlighted');
     Projects.highlightTag(tagName());
  }
  
  this.onmouseout = function(){
   tagEl.toggleClass('highlighted');
   Projects.clearHighlight();
  }
  
  this.onclick = function(){
   tagEl.toggleClass('selected');
   Projects.toggleSelect(tagName());
  }
  
}


Tag.fromTagElement = function(tagEl){
  return new Tag($(tagEl));
}

Projects = (function(){
  var selectedTags = [];
  var highlightedTag;
  
  var projects = [];
  var projectIdx = {};
  
  function hideOthers(els){
   $$('.project').difference(els).each(function(pjEl){
       $(pjEl.parentNode).fade(0.2);
   });
  }
  
  function tween(){
    $$('.project').each(function(pjEl){
        $(pjEl.parentNode).set('tween', {link : 'cancel', duration : '300ms' });
        $(pjEl.parentNode).fade(1);
    });
    
    if(selectedTags.length > 0){
      var selectedEls = selectedTags.map(function(tag){ return tagMap.get(tag) }).reduce(function(left, right){ return (right ? left.intersection(right) : left) });
      hideOthers(selectedEls);
    }
    
    if(highlightedTag && !selectedTags.contains(highlightedTag) ){
      var selectedEls = tagMap.get(highlightedTag);
      hideOthers(selectedEls);
    }
  }
  
  return {
    clearHighlight : function(){
      highlightedTag = false;
      tween();
    },
    highlightTag : function(tag){
      highlightedTag = tag;
      tween();
    },
    toggleSelect : function(tag){
      if(selectedTags.contains(tag)){
        selectedTags.erase(tag);
      }else{
        selectedTags.push(tag);
      }
      tween();
    },
    
    initialiseProjects : function(){
      $$('.project').each(function(pjEl){
          var pj =  new Project(pjEl)
          projects.push(pj);
          projectIdx[pj.name()] = projects.length - 1;
      });
    },  
    
    findNextProject : function(pj){
      return projects[projectIdx[pj.name()]+1];
    },
    findFirstProject : function(){
      return projects[0];
    },
    findPrevProject : function(pj){
      return projects[projectIdx[pj.name()]-1];
    },
    findLastProject : function(){
      return projects[projects.length-1];
    }

  };

})();

function Project(pjNode){
  this.bodyEl = pjNode;
  this.containerEl = pjNode.parentNode;

  this.containerEl.addEvent("click", onclick);
  this.containerEl.addEvent("mouseenter", onmouseover);
  this.containerEl.addEvent("mouseleave", onmouseout);
  
  var self = this;
  
  this.name = function(){
    return $(this.bodyEl).getElement("h2").get('text');
  }
  
  function onclick(){
    var modal = Modal.show(self);
  }
  
  function onmouseover(){
    $(self.containerEl).setStyle("z-index", "2");
    var fx = new Fx.Morph(self.containerEl, {duration : 100, link : 'cancel', fps: 20});
    fx.start({ 'font-size'   :  Zoom.currentZoom()+1,
               'top' : -Zoom.currentZoom()+1,
               'left' : -Zoom.currentZoom()+1 });
  }
  
  function onmouseout(){
    var fx = new Fx.Morph(self.containerEl, {duration : 100, link : 'cancel', fps : 20});
    fx.addEvent('complete', function(){ 
      $(self.containerEl).setStyle('font-size' , 'inherit');
      $(self.containerEl).setStyle('z-index' , '1');      
    } );
    fx.start({ 'font-size'   :  Zoom.currentZoom(),
               'top' : 0,
               'left' : 0 });  
  }
  
  this.next = function(){
    return Projects.findNextProject(this);
  }
  
  this.prev = function(){
   return Projects.findPrevProject(this);
  }
  
}

/**
  * Borrowed a little form moodalbox - http://www.e-magine.ro/moodalbox
  * MIT License
  */
var Modal = new (function(){
   
    function setup(){
        this.overlay = new Element('div').setProperty('id', 'modal_overlay').injectInside(document.body);
  		  this.center = new Element('div').setProperty('id', 'modal_center').setStyles({width: "700px", 
  		                                                                                height: "500px", 
  		                                                                                top: ((window.getSize().y-600)/2) + "px",
  		                                                                                left: ((window.getSize().x-700)/2) + "px"}).injectInside(document.body);
        this.header = new Element('div').setProperty('id', 'modal_header').setStyles({width: "100%", height: "100px", top : "0px", left : "0px"}).injectInside(this.center);
        this.closeLink = new Element('a').setProperty('id', 'modal_close').setProperty('href', '#').setProperty('text', 'Close').injectInside(this.header);  		                                                                                
        this.closeLink.onclick = this.close.bind(this);
        
        this.nextLink = new Element('a').setProperty('id', 'modal_next').setProperty('href', '#').setProperty('text', '>').injectInside(this.center);
        this.nextLink.addEvent("click", this.next.bind(this));
        this.nextLink.addEvent("mouseenter", this.nextOver.bind(this));
        this.nextLink.addEvent("mouseleave", this.nextOut.bind(this));        
        
        this.prevLink = new Element('a').setProperty('id', 'modal_prev').setProperty('href', '#').setProperty('text', '<').injectInside(this.center);
        this.prevLink.addEvent('click', this.prev.bind(this));
        this.prevLink.addEvent('mouseenter', this.prevOver.bind(this));
        this.prevLink.addEvent('mouseleave', this.prevOut.bind(this));
     
  		  this.contents = new Element('div').setProperty('id', 'modal_contents').setStyles({width: "600px", 
  		                                                                                    height: "400px", 
  		                                                                                    top: "100px",
  		                                                                                    left: "50px"}).injectInside(this.center);
    		this.overlay.onclick = this.close.bind(this);
    }
    setup = setup.bind(this);

    this.show = function(project){
      this.activeProject = project;
      if(!this.overlay){ setup(); }
      var fx = new Fx.Morph(this.overlay, {duration : 250, link : 'cancel', fps : 25});
   		this.center.style.display = 'none';
      this.overlay.style.display = 'block';
 		
      this.overlay.setStyle('opacity', 0); 
      function onFinish(){
        this.center.style.display = 'block';
        project.bodyEl.clone().injectInside(this.contents);
      }
      fx.addEvent('complete', onFinish.bind(this) );
      fx.start({opacity : 0.8});
    }
      
    this.close = function(){
      this.contents.empty();
      var fx = new Fx.Morph(this.overlay, {duration : 250, link : 'cancel', fps : 25});
		  this.center.style.display = 'none'
		  
		  function onFinish(){
  		  this.overlay.style.display = 'none';
		  }
      fx.addEvent('complete', onFinish.bind(this));
      fx.start({opacity : 0});
    }
    
    this.next = function(){
      this.contents.empty();
      this.activeProject = this.activeProject.next() || Projects.findFirstProject();
      this.activeProject.bodyEl.clone().injectInside(this.contents);
      this.nextOver();
    }
    
    this.nextOver = function(){
      var next = this.activeProject.next() || Projects.findFirstProject();
      this.nextLink.set('html', '&gt; <br/>' + next.name());
    }
    
    this.nextOut = function(){
      this.nextLink.set('text', '>');
    }
    
    this.prev = function(){
     this.contents.empty();
     this.activeProject = this.activeProject.prev() || Projects.findLastProject();
     this.activeProject.bodyEl.clone().injectInside(this.contents);
     this.prevOver();
    }
    
    this.prevOver = function(){
      var prev = this.activeProject.prev() || Projects.findLastProject();
      this.prevLink.set('html', '&lt; <br/>' + prev.name());
    }
    
    this.prevOut = function(){
      this.prevLink.set('text', '<');
    }


})();


var tagMap = $H();

function makeTagMap(){
  $each($$('.project'), function(pjEl){ 
      $each(pjEl.getElements('li.tag'), function(tagEl){
        var tag = tagEl.innerHTML;
        if(tagMap.has(tag)){
          tagMap.get(tag).push(pjEl);
        }else{
          tagMap.set(tag, [pjEl]);
        }
      });
  });
}

function writeTagMap(){
  var tags = tagMap.getKeys();
  tags = tags.sort(function(tagA, tagB){   return tagMap.get(tagB).length - tagMap.get(tagA).length   });
  tags = tags.filter(function(tag){ return (tagMap.get(tag).length > 2) });
  var tagList = "<ul>";
  tags.each(function(tag){ tagList += "<li onmouseover='Tag.fromTagElement(this).onmouseover()' onmouseout='Tag.fromTagElement(this).onmouseout()' onclick='Tag.fromTagElement(this).onclick()'>" + tag + "</li>"; });
  tagList += "</ul>";
  $('tagMap').innerHTML = tagList;
}


