﻿// modelview
var HIGHLIGHT = 0;
var SELECT = 1;
var mediaCount = 0;
var imgRep = 0;
var textRep = 1;
var repCount = 2;
var baseClassNames = ['mediaObject', 'mediaText'];
var _animate = 1;

function getShiftKey(e)
{
    theShift = (window.event) ? window.event.shiftKey : e.shiftKey;
    return(theShift);
}

function stopPropagation(e)
{
  if (window.event) {
    window.event.cancelBubble = true;     
  } else {
    e.stopPropagation();
  }
}

function node(text,theImg,theTags,bodyText, theID, theModel)
{
    this.theImg = theImg;
    this.text = text;
    this.theTagString = theTags;
    this.refBodyText = bodyText;   
    this.refID = theID;
    this.reps = new Array();
    this.tags = theTags;
    this.selected = false;
    this.model = theModel;
    this.classLabels = new Array();
    this.classLabels[HIGHLIGHT] = 'NoHighlight';
    this.classLabels[SELECT] = 'NoSelect';
    for (repType = 0; repType < repCount; repType++) {
        rep = new representation(repType, text, theImg, bodyText, theID, this);
        this.reps.push(rep);
    }
    this.currentRep = 0;
    this.updateClass();    
}

function representation(repType, text, theImg, bodyText, theID, theNode)
{
    if (repType == imgRep) 
    {
        this.ele = document.createElement('div');
        this.baseClassName = 'mediaObject';
        this.ele.id = 'mT' + mediaCount++;
        this.ele.mediaObject = theNode;
        this.img = document.createElement("img"); 
        this.img.src = theImg;
        this.img.mediaObject = theNode;
        this.img.style.height = '100px';
        this.img.style.width= '150px';           
        this.img.alt = bodyText;
        this.textNode = document.createElement("div");
        this.textNode.innerText = text;
        this.textNode.innerHTML = text;
        this.textNode.className = 'mediaText';
        this.textNode.mediaObject = theNode;    
        this.ele.appendChild(this.img);
        this.ele.appendChild(this.textNode);        
        this.ele.onmouseover = node.prototype.onNodeOver;
        this.ele.onmouseout = node.prototype.onNodeOut; 
        this.ele.onmousedown = node.prototype.selectNode;
    } else if (repType == textRep) {
        this.ele = document.createElement("tr");        
        this.eleYear = document.createElement("td");
        this.eleYear.className = 'textRowYear';
        this.eleYear.style.width='80px';
        this.eleYear.mediaObject = theNode;
        if (theNode.tags.year) {
            this.eleYear.innerHTML = theNode.tags.year[0];
        }        
        this.eleEntry = document.createElement("td");
//        this.eleEntry.style.width='800px';
        this.ele.appendChild(this.eleYear); 
        this.ele.appendChild(this.eleEntry);
        this.baseClassName = 'textElement';
        this.eleEntry.id = 'mT' + mediaCount++;
        this.eleEntry.mediaObject = theNode;
        this.eleEntry.innerText = text;
        this.eleEntry.innerHTML = text;
        this.ele.mediaObject = theNode;
        this.ele.className = 'textElement';
        this.ele.onmouseover = node.prototype.onNodeOver;
        this.ele.onmouseout = node.prototype.onNodeOut; 
        this.ele.onmousedown = node.prototype.selectNode;
        this.eleEntry.className = 'textRowElement';
              
/*        this.ele = document.createElement("li");
        this.baseClassName = 'textElement';
        this.ele.id = 'mT' + mediaCount++;
        this.ele.mediaObject = theNode;
        this.ele.innerText = text;
        this.ele.innerHTML = text;
        this.ele.onmouseover = node.prototype.onNodeOver;
        this.ele.onmouseout = node.prototype.onNodeOut; 
        this.ele.onmousedown = node.prototype.selectNode;
        this.ele.className = 'textElement';        
 */
    }            
}

node.prototype.setSize = function(w,h)
{
    this.reps[0].img.style.width = w+'px';
    this.reps[0].img.style.height= h+'px';
    this.reps[0].ele.style.width = w+'px';
    this.reps[0].ele.style.height = h+30+'px';
    this.reps[0].textNode.style.width = w+'px';
    this.reps[0].textNode.style.height = 30 + 'px';
}


node.prototype.onNodeOver = function(e)
{
    ts = getEventSrc(getEvent(e));
    mo = ts.mediaObject;
    mo.highLight();
    for (taggroup in mo.tags) {
        mo.model.tagList[taggroup].clear();
        tagl = mo.model.tagList[taggroup];
        tl = mo.tags[taggroup];
        tl.each(function(tag) {
            tagl.highLightByTag(tag); 
        });
    }
    stopPropagation(e);
}

node.prototype.onNodeOut = function(e)
{
    ts = getEventSrc(getEvent(e));
    mo = ts.mediaObject;
    if (!mo) return;
    mo.clearHighLight();
    for (taggroup in mo.tags) {
        mo.model.tagList[taggroup].clear();
    }
    stopPropagation(e);   
}

node.prototype.selectNode = function(e)
{
    ts = getEventSrc(getEvent(e));
    mo = ts.mediaObject;
    theShift = getShiftKey(e);
    mo.model.clearHighlights();
    mo.model.clearAllSelection();
    mo.doSelect();
    mo.model.doSelectCallback(mo);
 /*   if (theShift == false) {
        mo.model.clearHighlights();
        mo.model.clearAllSelection();
        mo.doSelect();
        mo.model.doSelectCallback(mo);
    } else {
        mo.model.clearHighlights();
        mo.toggleSelect();
        if (mo.selected) {
            mo.model.doSelectCallback(mo);
        }
    }
    */
    stopPropagation(e);
}

node.prototype.getRepElement = function()
{
    rep = this.reps[this.model.currentRep]
    return(rep.ele);
}

node.prototype.updateClass = function()
{
    className = '';
    for (var i=0; i < 2;i++) { 
        className += " " + this.reps[this.model.currentRep].baseClassName + this.classLabels[i];
    }
    ele = this.getRepElement();
    ele.className = this.reps[this.model.currentRep].baseClassName + className;    
    if (this.classLabels[HIGHLIGHT] == 'Highlight') {     
       ele.style.background = 'Teal';
    } else {
        if (ele['nodeColor']) {
           ele.style.background = ele.nodeColor;
        }
        else {
           ele.style.background = '#333';
        }
    }
}

node.prototype.highLight = function()
{
    this.classLabels[HIGHLIGHT] = 'Highlight';    
    this.updateClass();    
}

node.prototype.clearHighLight = function()
{
    this.classLabels[HIGHLIGHT] = 'NoHighlight';    
    this.updateClass();
}

node.prototype.doSelect = function()
{
    this.classLabels[SELECT] = 'Select';
    this.selected = true;
    this.updateClass();
}

node.prototype.doDeSelect = function()
{
    this.classLabels[SELECT] = 'NoSelect';
    this.selected = false;
    this.updateClass();
}

node.prototype.toggleSelect = function()
{
    if (this.selected) {
        this.classLabels[SELECT] = 'NoSelect';
        this.selected = false;
    } else {
        this.classLabels[SELECT] = 'Select';
        this.selected = true;
    }
    this.updateClass();
}

node.prototype.matchFilter = function(curFilter)
{
    var totalMatched = true;    
    for (aFilterGroup in curFilter) {
        aList = curFilter[aFilterGroup];
        taglist = this.tags[aFilterGroup];
        var groupMatched = false;        
        aList.each(function(t1) {
            taglist.each(function(t2) {
                if (t1 == t2) {
                    groupMatched = true;
                }
            });            
        });
        if (!groupMatched) totalMatched = false;
    }
    return(totalMatched);       
}



function model()
{
    this.nodeList = new Array();
    this.currentRep = imgRep;
    this.containers = new Object();
    this.leftSide = 50;
    this.topSide = 40;
    this.spacing = 175;    
    this.elementWidth = 120;
    this.elementHeight = 80;
    this.aspect = 1.5;
    this.columns = 5;
    this.tagList = new Object();  
    this.sortOrderKeys = new Object();     
}


model.prototype.addTagList = function(groupName, tl)
{
    this.tagList[groupName] = tl;
}

model.prototype.getAllNodes = function()
{
    return(this.nodeList);
}

model.prototype.getTagGroups = function()
{
  var localTagList = new Object();
    this.nodeList.each(function(node) {
        tagGroups = node.tags;
        for (aGroup in tagGroups) {
            if (!localTagList.hasOwnProperty(aGroup)) {
                localTagList[aGroup] = 1;
            } else {
                localTagList[aGroup]++;
            }
        }        
    });
    return(localTagList);

}

model.prototype.getTagCount = function(tagName, tagArray)
{
    var localTagList = new Object();
    tagArray.each(function(tag) {
        localTagList[tag.key] = 0;
    });
    
    tempFilter = new Object();
    for (groupName in this.currentFilter) {
        if (groupName != tagName) {
            tempFilter[groupName] = this.currentFilter[groupName];
        }
    }    
    
    this.nodeList.each(function(node) {
        if (node.matchFilter(tempFilter)) {
            tagNodes = node.tags[tagName];
            tagNodes.each(function(ltag) {        
                if (!localTagList.hasOwnProperty(ltag)) {
                    localTagList[ltag] = 1;
                } else {
                    localTagList[ltag]++;
                }
            });
        }
    });
    return(localTagList);
}

model.prototype.getAllTags = function(tagName)
{
    var localTagList = new Object();
    this.nodeList.each(function(node) {
        tagNodes = node.tags[tagName];
        tagNodes.each(function(ltag) {
            if (!localTagList.hasOwnProperty(ltag)) {
                localTagList[ltag] = 1;
            } else {
                localTagList[ltag]++;
            }
        });        
    });
    return(localTagList);
}

model.prototype.highlightNodes = function(nodeList)
{
    nodeList.each(function(node) {
        node.highLight() });
}

model.prototype.clearHighlights = function()
{
    this.nodeList.each(function(node) {
        node.clearHighLight() });
}

model.prototype.selectNodes = function(nodeList)
{
    nodeList.each(function(node) {
        node.doSelect() });
}

model.prototype.clearSelection = function(nodeList)
{
    nodeList.each(function(node) {
        node.doDeSelect() });
}
        
model.prototype.getTagLists = function()
{
    return(this.tagLists);
}
        

model.prototype.initTagLists = function(divArea)
{    
    tg = this.getTagGroups();
    for (aGroupName in tg) {
        tags = this.getAllTags(aGroupName);
        myTagList = new tagList(aGroupName, tags, divArea, this);
        myTagList.tagSelectCallback = "checkForSelected()";
        this.addTagList(aGroupName, myTagList);
    }
}

model.prototype.clearAllSelection = function()
{
    this.nodeList.each(function(node) {
        node.doDeSelect() });
}

model.prototype.getNodesByTag = function(groupName, tag)
{
    var localTagList = new Object();
    var localTagArray = new Array();
    this.nodeList.each( function(node) {
        tagNodes = node.tags[groupName];
        tagNodes.each( function(ltag) {
            if (ltag == tag) {
                localTagArray.push(node);
            }
        });        
    });
    return(localTagArray);
}


model.prototype.getVisibleSelected = function()
{
    var localArray = new Array();
    
    this.nodeList.each(function(node) {
        ele = node.getRepElement();
        if ((node.selected) && (ele.style.display != "none")) {
            localArray.push(node);        
        }
    });
    return(localArray);   
}

model.prototype.colorNodesFromGroup = function(groupName)
{
    theTagList = this.tagList[groupName];
    for (tag in theTagList.tags) {    
        nl = this.getNodesByTag(groupName, tag);
        nl.each(function(node) {
            ele = node.getRepElement();
            hueEle = theTagList.hueMap[tag];
            ele.style.background = hueEle.style.background;
            ele.nodeColor = hueEle.style.background;
        });
    }
}


model.prototype.highlightNodesByTag = function(groupName, tag)
{
    nodeList = this.getNodesByTag(groupName, tag);
    this.highlightNodes(nodeList);
}

model.prototype.selectNodesByTag = function(groupName, tag)
{
    nodeList = this.getNodesByTag(groupName, tag);
    this.selectNodes(nodeList);
}

model.prototype.doLayoutVisible = function(containerId, speed)
{
    var cont = document.getElementById(containerId);  
    var count = 0;
    this.nodeList.each( function(someNode) {
        ele = someNode.getRepElement();
        if (ele.style.display == "block") {
//            cont.appendChild(ele);            
            if (this.currentRep == imgRep) {
                xpos = this.leftSide + (count % this.columns) * (this.spacing+15);
                ypos = this.topSide + Math.floor(count/this.columns)*this.spacing;
                if (_animate && speed > 0) {
                    effect = new Effect.Move(ele, {x: xpos, y: ypos, duration: speed , mode:'absolute'});
                }
                else {
                    ele.style.left = xpos + "px";
                    ele.style.top =  ypos + "px";
                }
            }
            count++;
        }
    }.bind(this));
}

model.prototype.clearTagChecks = function()
{
    for (tl in this.tagList) {
        this.tagList[tl].clearChecks();
    }
}

model.prototype.doLayoutAll = function(containerId, speed)
{
    this.currentFilter = new Object();
    var cont = document.getElementById(containerId);  
    this.clearTagChecks();
    this.nodeList.each( function(someNode,i) {
        ele = someNode.getRepElement();
  //      cont.appendChild(ele);            
        if (this.currentRep == imgRep) {
            xpos = this.leftSide + (i % this.columns) * (this.spacing+15);
            ypos = this.topSide + Math.floor(i/this.columns)*this.spacing;
            if (_animate && speed > 0) {
                e1 = new Element.setOpacity(ele, {opacity: 1.0, duration: 0.5});
                //effect1 = new Effect.Appear(ele, {duration: speed});
                effect = new Effect.Move(ele, {x: xpos, y: ypos, duration: speed, mode:'absolute' });
            }
            else {
                e1 = new Element.setOpacity(ele, {opacity: 1.0, duration: 0.5});
                ele.style.left = xpos + "px";
                ele.style.top =  ypos + "px";
            }
        } else {
               e1 = new Element.setOpacity(ele, {opacity: 1.0, duration: 0.5});               
        }
        ele.style.display = "block";
        someNode.visible = true;

      }.bind(this));
      this.updateCounts();
}

model.prototype.addAllToView = function(rep)
{
    cid = this.containers[rep];
    this.doAddAllToView(cid, rep);
}

model.prototype.removeAllFromView = function(containerID)
{
    cont = $(containerID);
    children = cont.childNodes;
    for (x=children.length-1; x>=0; x--) {
        ele = children.item(x);
        cont.removeChild(ele);
    }
}


model.prototype.getOrderedList = function(sortKey,asc)
{
    if (sortKey == 'project') {
        this.nodeList.sort(function(a,b) {           
            if (a.text < b.text) return(-1 * asc);
            else return(1 * asc);            
        });
        return(this.nodeList);
    }
    this.nodeList.sort(function(a,b) {
        if (a.tags[sortKey]) {
            if (a.tags[sortKey][0] < b.tags[sortKey][0]) return(-1 * asc);
            else return(1 * asc);
        } else {
            return(0);
        }        
    });
    return(this.nodeList);
}

model.prototype.sortOrder = function(containerID, rep, sortKey) 
{
    this.removeAllFromView(containerID);
    if (this.sortOrderKeys[sortKey]) {
        asc = this.sortOrderKeys[sortKey] * -1.0;
        this.sortOrderKeys[sortKey] = asc;
    } else {
        this.sortOrderKeys[sortKey] = 1.0;
        asc = 1.0;
    }
    newOrder = this.getOrderedList(sortKey,asc);
    this.doAddListToView(containerID, rep, newOrder);
    cont = $(containerID);
    cont.style.display = 'none';   
    this.layoutSelected(0.5);
    cont.style.display = 'block';
}

model.prototype.doAddListToView = function(containerID, rep, orderedList)
{
    var cont = document.getElementById(containerID);
    saveRep = this.currentRep;
    this.currentRep = rep;    
    orderedList.each ( function(someNode) {
        ele = someNode.getRepElement();
        cont.appendChild(ele);
    });
    this.currentRep = saveRep;
}

model.prototype.doAddAllToView = function(containerID, rep)
{   
    var cont = document.getElementById(containerID);
    saveRep = this.currentRep;
    this.currentRep = rep;    
    this.nodeList.each ( function(someNode) {
        ele = someNode.getRepElement();
        cont.appendChild(ele);
    });
    this.currentRep = saveRep;
}

model.prototype.setupCounter = function(counterID)
{
    this.counterID = counterID;
}

model.prototype.setupContainer=function(containerID, rep)
{
    this.containers[rep] = containerID;
}

model.prototype.layoutSelected = function(speed)
{
 //   this.doLayoutSelected(this.containers[this.currentRep], this.currentRep,speed);
    this.doLayoutFiltered(this.containers[this.currentRep], this.currentRep,speed);
}

model.prototype.layoutAll = function(speed)
{
    this.doLayoutAll(this.containers[this.currentRep],speed);
}

model.prototype.layoutVisible = function(speed)
{
   this.doLayoutVisible(this.containers[this.currentRep],speed);
}

model.prototype.doLayoutFiltered = function(containerID, rep, speed)
{
    var cont = document.getElementById(containerID);
    saveRep = this.currentRep;
    this.currentRep = rep;   
    var count = 0;
    this.nodeList.each ( function(someNodeEntry) {
        ele = someNodeEntry.getRepElement();
        if (!this.currentFilter) {
            satFilter = true;
        } else {
            satFilter = someNodeEntry.matchFilter(this.currentFilter);
        }
        if (satFilter) {        
            if (this.currentRep == imgRep) {
                xpos = this.leftSide + (count % this.columns) * (this.spacing+15);
                ypos = this.topSide + Math.floor(count/this.columns)*this.spacing;
                if (_animate && speed > 0) {
                    e1 = new Element.setOpacity(ele, {opacity: 1.0, duration: 0.5});
                    effect = new Effect.Move(ele, {x: xpos, y: ypos, duration: speed, mode:'absolute' });
                }
                else {
                    e1 = new Element.setOpacity(ele, {opacity: 1.0, duration: 0.5});
                    ele.style.left = xpos + "px";
                    ele.style.top =  ypos + "px";
                }
            }
            e1 = new Element.setOpacity(ele, {opacity: 1.0, duration: 0.5});
            ele.style.display = "block";
            someNodeEntry.visible = true;
            count++;
        } else
        {
          if (_animate && speed > 0) {
            effect = new Effect.Fade(ele, {duration:  speed});
          } else {
            ele.style.display = "none";
            ele.selected = false;
          }
          someNodeEntry.visible = false;
        }
    }.bind(this));
    this.currentRep = saveRep;
    this.updateCounts();
}

model.prototype.doLayoutSelected = function(containerID, rep, speed)
{
    var cont = document.getElementById(containerID);


    count = 0;
    saveRep = this.currentRep;
    this.currentRep = rep;   
    this.nodeList.each ( function(someNodeEntry) {
        ele = someNodeEntry.getRepElement();
        if ((someNodeEntry.selected) && (ele.style.display != "none")) {                
            if (this.currentRep == imgRep) {
                xpos = this.leftSide + (count % this.columns) * (this.spacing+15);
                ypos = this.topSide + Math.floor(count/this.columns)*this.spacing;
                if (_animate && speed > 0) {
                    effect = new Effect.Move(ele, {x: xpos, y: ypos, duration: speed, mode:'absolute' });
                }
                else {
                    ele.style.left = xpos + "px";
                    ele.style.top =  ypos + "px";
                }
            }
            ele.style.display = "block";
            someNodeEntry.visible = true;
            count++;
        } else
        {
          if (_animate && speed > 0) {
            effect = new Effect.Fade(ele, {duration:  speed});
          } else {
            ele.style.display = "none";
            ele.selected = false;
          }
          someNodeEntry.visible = false;
        }
    }.bind(this));
    this.currentRep = saveRep;
    this.updateCounts();
}

model.prototype.updateCounts = function()
{
    for (aGroup in this.tagList) {
        newl = modelView.getTagCount(aGroup, this.tagList[aGroup].tagArray);
        this.tagList[aGroup].updateCounts(newl);
    }
    totCount = this.getCurrentDisplayedCount();
    this.updateTotal(totCount);
}

model.prototype.getCurrentDisplayedCount = function()
{
    var count = 0;
    this.nodeList.each ( function(someNodeEntry) {
        if (someNodeEntry.visible) count++;
    });
    return(count);
}

model.prototype.updateTotal = function(n)
{
    el = $(this.counterID);
    el.innerHTML = n + " out of " + this.totalCount + " displayed";
}

model.prototype.setAllSize = function(w,h)
{
    this.elementWidth = w;
    this.elementHeight = h;
    this.nodeList.each(function(someNode) {
        someNode.setSize(w,h);
    });
}

model.prototype.getVisibleSelectedCount = function()
{
    count = 0;
    this.nodeList.each(function(someNodeEntry) {
        ele = someNodeEntry.getRepElement();
        if ((someNodeEntry.selected) && (ele.style.display != "none")) {
            count+=1;
        }
    });
    return(count);
}

model.prototype.doSelectCallback = function(mo)
{
   callback = this.selectCallback + '(mo)';
   eval(callback);
}