/**
 * Hardware objects.
 * @author Mark Woodman
 */

Hardware.NORTH_OFFSET = new Array(0,-1);
Hardware.EAST_OFFSET = new Array(1,0);
Hardware.SOUTH_OFFSET = new Array(0,1);
Hardware.WEST_OFFSET = new Array(-1,0);
Hardware.NAMES = new Array("EmptySlot", "Server", "Laptop", "Printer", "Scanner", "Hub", "EthernetStraight", "EthernetCorner");
Hardware.FILE_NAMES = new Array("blank", "server", "laptop", "printer", "scanner", "hub", "cablestraight", "cablecorner");
Hardware.ORIENTATIONS = new Array("north", "south", "east", "west");
Hardware.STATES = new Array("on","off");
Hardware.IMAGE_DIR = "images/";
Hardware.TYPES = new Object();

function Hardware()
{
    this.online = false;
    this.northHotspots = null;
    this.eastHotspots = null;
    this.southHotspots = null;
    this.westHotspots = null;
    this.hashCode = null;
    this.server = false;
    this.imageNode;
}

Hardware.registerType = function(className, hashCode)
{
   Hardware.TYPES[hashCode] = className;    
}

Hardware.newInstance = function(gridLocation, aHash)
{
    // Determine class
    var className = Hardware.TYPES[aHash.charAt(0)];
    if(className==null) 
    {
        alert("Bad data: " + aHash);
        className = "EmptySlot";
    }
    
    // Determine orientation
    var orientCode = aHash.charAt(1);
    var orientation = "north";
    
    if(orientCode=="n") orientation = "north";
    if(orientCode=="s") orientation = "south";
    if(orientCode=="e") orientation = "east";
    if(orientCode=="w") orientation = "west";
    
    // Compose instance statement
    var stmt = "new " + className + "(new Array(" + gridLocation[0] +
               "," + gridLocation[1] + "), \"" + orientation +"\")";

    // Eval statement to get instance
    return eval(stmt);
}

Hardware.prototype.setImage = function(imageNode)
{
    this.imageNode = imageNode;
    this.imageNode.setAttribute("title",this.getDescription());
    this.imageNode.setAttribute("src", this.getFileName());
}

Hardware.prototype.getImage = function()
{
    if(this.imageNode==null) 
    {
        var img = new Image(41, 41);
        img.setAttribute("border","0");
        img.setAttribute("gridx",this.gridLocation[0]);
        img.setAttribute("gridy",this.gridLocation[1]);
        img.setAttribute("title", this.getDescription());
        img.onclick = function(){ Hardware.imageClicked(this); };
        this.setImage(img);
        debug("Created image for " + this.gridLocation[0] + "," + this.gridLocation[1]);
    }
    return this.imageNode;   
}

Hardware.imageClicked = function(imgNode)
{
    Grid.instance.pointClicked(imgNode.getAttribute("gridx"), imgNode.getAttribute("gridy"));
}

Hardware.prototype.getFileName = function()
{
    var status = (this.isOnline()==true) ? "on" : "off";
    var fileName;
    if(this.filePrefix=="blank")
    {
        fileName = "blank.png";
    }
    else
    {
        fileName = this.filePrefix + "_" + this.orientation + "_" + status + ".png";
    }
    return Hardware.IMAGE_DIR + fileName;
}

Hardware.prototype.getOnclick = function()
{
    //return "Grid.instance.pointClicked(" 
    return "alert(" 
           + this.gridLocation[0] + "," 
           + this.gridLocation[1] +");";
}

Hardware.prototype.refreshImage = function()
{
    this.imageNode.setAttribute("title", this.getDescription());
    
    var newSrc = this.getFileName();
    var oldSrc = this.imageNode.getAttribute("src");
    if(newSrc!=oldSrc && oldSrc.indexOf(newSrc)<0)
    {
        debug("Changing src at " + this.gridLocation[0] + "," + this.gridLocation[1] + " from " + oldSrc + " to " + newSrc);
        this.imageNode.setAttribute("src", newSrc);
    }
}

Hardware.prototype.isOnline = function()
{
    if(this.isServer()==true)
    {
        return true;
    }
    else
    {
        return this.online;   
    }
}

Hardware.prototype.setIsOnline = function(_online)
{
    if(this.isServer()==true)
    {
        this.online = true;
    }
    else
    {
        this.online = _online;   
    }
}

Hardware.prototype.isServer = function()
{
    return this.server;
}

Hardware.prototype.getDescription = function()
{
    var status = (this.isOnline()==true) ? "Online" : "Offline";  
    return this.displayName + ": " + status;
}

Hardware.prototype.hash = function()
{
    return this.hashCode + this.orientation.charAt(0);   
}

Hardware.prototype.rotate = function()
{
    // Determine new position
    if(this.orientation=="north")
    {
        this.orientation = "east";
    }   
    else if(this.orientation=="east")
    {
        this.orientation = "south";
    } 
    else if(this.orientation=="south")
    {
        this.orientation = "west";
    } 
    else if(this.orientation=="west")
    {
        this.orientation = "north";
    }
    
    // Determine connectivity
    Grid.instance.requestPing();
}

Hardware.prototype.getCurrentHotspots = function()
{
    return this.getHotspots(this.orientation);
}

Hardware.prototype.getHotspots = function(orientation)
{
    return this[orientation + "Hotspots"];
}

Hardware.prototype.findCoordinate = function(offsetCoord)
{
    var x = this.gridLocation[0] + offsetCoord[0];
    var y = this.gridLocation[1] + offsetCoord[1];
    return new Array(x,y);
}

Hardware.prototype.isConnectedTo = function(neighborHardware)
{
    var hotspots = this.getCurrentHotspots();
    for(var i=0;i<hotspots.length;i++)
    {
       var hotspotCoord = this.findCoordinate(hotspots[i]);
       if(hotspotCoord[0]==neighborHardware.gridLocation[0] &&
          hotspotCoord[1]==neighborHardware.gridLocation[1]) return true;
    }   
    return false;
}

Hardware.prototype.ping = function(notified)
{
    this.setIsOnline(true);
    notified[this.gridLocation]=true;
    var neighbors = this.getNeighbors(this.orientation);
    for(var i=0;i<neighbors.length;i++)
    {
       var neighbor = neighbors[i];
       if(!notified[neighbor.gridLocation] && neighbor.isConnectedTo(this))
       {
            neighbor.ping(notified);
       }
    }
}

Hardware.prototype.getNeighbors = function(orientation)
{
    var hotspots = this.getHotspots(orientation);
    var neighbors = new Array();
    if(hotspots)
    {
        for(var i=0;i<hotspots.length;i++)
        {
           var hotspotCoord = this.findCoordinate(hotspots[i]);
           var row = Grid.instance.hardwareMatrix[hotspotCoord[0]];
           if(row)
           {
               var neighbor = row[hotspotCoord[1]];
               if(neighbor) neighbors.push(neighbor);
            }
        }
    }
    return neighbors;
}

BasicHardware.prototype = new Hardware;
function BasicHardware()
{
    this.northHotspots = new Array(Hardware.NORTH_OFFSET);  
    this.eastHotspots = new Array(Hardware.EAST_OFFSET);
    this.southHotspots = new Array(Hardware.SOUTH_OFFSET);
    this.westHotspots = new Array(Hardware.WEST_OFFSET);
}

Server.prototype = new BasicHardware;
Server.HASHCODE = "a";
Hardware.registerType("Server", Server.HASHCODE);
function Server(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.online = true;
    this.filePrefix = "server";
    this.displayName = "Server";
    this.hashCode = Server.HASHCODE;
    this.server = true;
}

Laptop.prototype = new BasicHardware;
Laptop.HASHCODE = "b";
Hardware.registerType("Laptop", Laptop.HASHCODE);
function Laptop(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.filePrefix = "laptop";
    this.displayName = "Laptop";
    this.hashCode = Laptop.HASHCODE;
}

Printer.prototype = new BasicHardware;
Printer.HASHCODE = "c";
Hardware.registerType("Printer", Printer.HASHCODE);
function Printer(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.filePrefix = "printer";
    this.displayName = "Laser Printer";
    this.hashCode = Printer.HASHCODE;
}

Scanner.prototype = new BasicHardware;
Scanner.HASHCODE = "d";
Hardware.registerType("Scanner", Scanner.HASHCODE);
function Scanner(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.filePrefix = "scanner";
    this.displayName = "Flattop Scanner";
    this.hashCode = Scanner.HASHCODE;
}

EthernetStraight.prototype = new Hardware;
EthernetStraight.HASHCODE = "e";
Hardware.registerType("EthernetStraight", EthernetStraight.HASHCODE);
function EthernetStraight(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.northHotspots = new Array(Hardware.NORTH_OFFSET, Hardware.SOUTH_OFFSET);  
    this.eastHotspots = new Array(Hardware.EAST_OFFSET, Hardware.WEST_OFFSET);
    this.southHotspots = new Array(Hardware.NORTH_OFFSET, Hardware.SOUTH_OFFSET);
    this.westHotspots = new Array(Hardware.EAST_OFFSET, Hardware.WEST_OFFSET);
    this.filePrefix = "cablestraight";
    this.displayName = "Ethernet Cable";
    this.hashCode = EthernetStraight.HASHCODE;
}

EthernetCorner.prototype = new Hardware;
EthernetCorner.HASHCODE = "f";
Hardware.registerType("EthernetCorner", EthernetCorner.HASHCODE);
function EthernetCorner(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.northHotspots = new Array(Hardware.NORTH_OFFSET, Hardware.WEST_OFFSET);  
    this.eastHotspots = new Array(Hardware.NORTH_OFFSET, Hardware.EAST_OFFSET);
    this.southHotspots = new Array(Hardware.EAST_OFFSET, Hardware.SOUTH_OFFSET);
    this.westHotspots = new Array(Hardware.SOUTH_OFFSET, Hardware.WEST_OFFSET);
    this.filePrefix = "cablecorner";
    this.displayName = "Ethernet Cable";
    this.hashCode = EthernetCorner.HASHCODE;
}

Hub.prototype = new Hardware;
Hub.HASHCODE = "g";
Hardware.registerType("Hub", Hub.HASHCODE);
function Hub(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.northHotspots = new Array(Hardware.NORTH_OFFSET, Hardware.EAST_OFFSET, Hardware.WEST_OFFSET);  
    this.eastHotspots = new Array(Hardware.NORTH_OFFSET, Hardware.EAST_OFFSET, Hardware.SOUTH_OFFSET);
    this.southHotspots = new Array(Hardware.EAST_OFFSET, Hardware.SOUTH_OFFSET, Hardware.WEST_OFFSET);
    this.westHotspots = new Array(Hardware.SOUTH_OFFSET, Hardware.WEST_OFFSET, Hardware.NORTH_OFFSET);
    this.filePrefix = "hub";
    this.displayName = "Hub";
    this.hashCode = Hub.HASHCODE;
}

EmptySlot.prototype = new Hardware;
EmptySlot.HASHCODE = "";
function EmptySlot(gridLocation, orientation)
{
    this.gridLocation = gridLocation;
    this.orientation = orientation;
    this.northHotspots = new Array();  
    this.eastHotspots = new Array();
    this.southHotspots = new Array();
    this.westHotspots = new Array();
    this.filePrefix = "blank";  
    this.displayName = "";
    this.hashCode = EmptySlot.HASHCODE;
}

EmptySlot.prototype.getDescription = function() { return ""; }
EmptySlot.prototype.hash = function() { return ""; }
EmptySlot.prototype.isOnline = function() { return true;}
EmptySlot.prototype.setIsOnline = function() {}
EmptySlot.prototype.rotate = function() {}
EmptySlot.prototype.refreshImage = function() {}
EmptySlot.prototype.findPathToServer = function(orientation, checked)
{
    checked[this]==true;
    return false;   
}