//
// glif.js
//
// Description: 
// This Javascript is associated with the HTML form GLIF.html. It can
// be used to generate NDL file given user input.
//
// Author: 
// Paola Grosso - SNE group - University of Amssterdam
//
// History: 
// V1.0 = Apr. 25 2006
// V1.1 = Jan. 15 2007 - Added code to handle multiple locations
// V2.0 = Mar. 05 2007 - Changed to produce an RDF file that is
//                       conform to the latest topology schema


// Global variables declaration
gCurrentNumberOfLocations =1;
gCurrentNumberOfDevices = 3 ;
listOfDevices = new Array();
listOfInterfacesPerDevice = new Array();
listOfInterfaces = new Array();
var locationArrayFilled = false;
var deviceFilled = false;
var interfaceFilled = false;
var interfaceTableExist = false;
var ndl;

//Selection lists
var listOfInterfaceTypes = '<option value=""><option value="OC12Interface">OC12 Interface<option value="OC48Interface">OC48 Interface<option value="OC192Interface">OC192 Interface<option value="EthernetInterface">Ethernet Interface<option value="IPinterface">IP Interface';

//
// addLocationField()
// Function that adds a new location
// 
function addLocationField()
{
  locationTableBody = document.getElementById('locationtable');
  tr = document.createElement('tr');
  tr.appendChild(addCol("Identifier"));
  tr.appendChild(addCol('<input name=\"location_id_'+gCurrentNumberOfLocations+'\" value="">'));
  tr.appendChild(addCol("(Human readable) name"));
  tr.appendChild(addCol('<input name=\"location_name_'+gCurrentNumberOfLocations+'\" value="">'));
  tr.appendChild(addCol("Latitude"));
  tr.appendChild(addCol('<input name=\"location_lat_'+gCurrentNumberOfLocations+'\" value="">'));
  tr.appendChild(addCol("Longitude"));
  tr.appendChild(addCol('<input name=\"location_long_'+gCurrentNumberOfLocations+'\" value="">'));

  locationTableBody.appendChild(tr);
  gCurrentNumberOfLocations++;
}

//
// createDeviceTable()
// Function that creates the basic table for the device information
//
function createDeviceTable()
{ 
  for (i = 1; i <= 3; i++){
    addDeviceField();
  }
}

//
// addDeviceField()
// Function that creates a row available for user input in the device
// table. The function is called at the very beginning when generating
// the basic table by createDeviceTable; it can also be invoked by the
// user if she needs more input row via the form button "Add a Device"
//
function addDeviceField()
{          
  deviceTableBody = document.getElementById('devicetable');
  tr = document.createElement('tr');
  tr.appendChild(addCol("Device"));
  tr.appendChild(addCol('<input name=\"device_'+gCurrentNumberOfDevices+'\" value="">'));
  tr.appendChild(addCol("Device's location id"));
  tr.appendChild(addCol('<input name=\"device_loc_'+gCurrentNumberOfDevices+'\" value="">'));
  deviceTableBody.appendChild(tr);
  gCurrentNumberOfDevices++;
}

//
// createInterfaceTable():
// Function that creates the tables for provinding input on the
// interfaces for all the known devices in this network
//
function createInterfaceTable(device)
{    
  inttables = document.getElementById('interfacetables');
  if (!interfaceTableExist){
    if(getListOfDevices()){
      for (dev =0; dev < listOfDevices.length; dev++){
	thisDevice = listOfDevices[dev];
	listOfInterfacesPerDevice[dev]=0;
	var newEl = document.createElement('TABLE');
	newEl.setAttribute('ID', 'TABLE_'+dev);
	var tmp = document.createElement('TBODY');
	tmp.setAttribute('ID','TBODY_'+dev);
	tmp.innerHTML = '<TBODY>';
	var tr = document.createElement('TR');
	tr.appendChild(addCol('Device '));
	tr.appendChild(addCol(' <font size =3 color="blue"> ' + thisDevice.name + '</font>     '));
	tr.appendChild(addCol('Interface <code>'+ thisDevice.name +':</code>'));
	tr.appendChild(addCol('<input name="'+thisDevice.tag+'_intf_0" value="eth0">'));
        tr.appendChild(addCol('Type (optional)<select name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_interfaceType">'+listOfInterfaceTypes+'</select>'));
        tr.appendChild(addCol('<select name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_connType"><option value="connectedTo">connectedTo<option value="linkedTo">linkedTo</select>'));
	tr.appendChild(addCol('<input name="'+thisDevice.tag+'_intf_0_connection" value="">'));
	tr.appendChild(addCol('seeAlso'));
	tr.appendChild(addCol('<input name="'+thisDevice.tag+'_intf_0_seeAlso" value="">'));
	tr.appendChild(addCol('Capacity'));
	tr.appendChild(addCol('<input name="'+thisDevice.tag+'_intf_0_capacity" value="" fontSize="12pt">'));
	tmp.appendChild(tr);
	newEl.appendChild(tmp);
	inttables.appendChild(newEl);
	listOfInterfacesPerDevice[dev]++;
	var button = document.createElement('button_'+dev);
	button.innerHTML = '<input type="button" value="Add interface for ' + thisDevice.name + '\" onclick="addInterfaceRow(' + dev + ')\"><br><hr>';
	inttables.appendChild(button);
	document.innerHTML = '<br> <br><hr>';
      }
      interfaceTableExist = true;
    }
    else {
      alert("You need to define at least one device");
    }
  }
  else{
    alert("You already generated the interfaces table. Please first remove interfaces to re-generate!");
  }
}

//
// addInterfaceRow()
// Function that add one extra input row to a table for a device
// interfaces
//
function addInterfaceRow(dev){
  thisDevice = listOfDevices[dev];
  tableBody = document.getElementById('interfacetables').getElementsByTagName('TABLE')[dev].getElementsByTagName('TBODY')[0];
  var tr = document.createElement('TR');
  tr.appendChild(addCol('Device'));
  tr.appendChild(addCol('<font size =3 color="blue"> ' + listOfDevices[dev].name + '</font>     '));
  tr.appendChild(addCol('Interface <code>'+ listOfDevices[dev].name +':</code>'));
  tr.appendChild(addCol('<input name="'+ thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev]   +'" value="">'));
  tr.appendChild(addCol('Type (optional) <select name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_interfaceType">'+listOfInterfaceTypes));	
  tr.appendChild(addCol('<select name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_connType"><option value="connectedTo">connectedTo<option value="linkedTo">linkedTo</select>'));	
  tr.appendChild(addCol('<input name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_connection" value="">'));
  tr.appendChild(addCol('seeAlso'));
  tr.appendChild(addCol('<input name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_seeAlso" value="">'));
  tr.appendChild(addCol('Capacity'));
  tr.appendChild(addCol('<input name="' + thisDevice.tag +'_intf_'+listOfInterfacesPerDevice[dev] +'_capacity" value="">'));
  listOfInterfacesPerDevice[dev]++;
  tableBody.appendChild(tr);
  interfaceFilled = false;
}

//
// removeInterfaceTables()
// Function that removes the interface tables, in case the user needs
// to re-input this information. this can happen if the user wants to
// add an extra device to the network.
//
function removeInterfaceTables()
{
  inttables = document.getElementById('interfacetables');
  while (inttables.hasChildNodes(0)){
    inttables.removeChild(inttables.firstChild);
  }
  deviceFilled = false;
  interfaceTableExist = false;
}



//
// getListOfDevices()
// Function that retrieves all the devices known for this network, and
// fills the list of interfaces that will be used to generate the NDL file
//
function getListOfDevices()
{
  if (!deviceFilled){
    listOfDevices = new Array();
    for (dev = 0 ; dev <  gCurrentNumberOfDevices; dev++){
      if(document.glif_form.elements['device_' + dev].value != ''){
	deviceName = document.glif_form.elements['device_' + dev].value;
	deviceLocation = undefined;
	if (document.glif_form.elements['device_loc_'+dev].value !=''){      
	  deviceLocation = document.glif_form.elements['device_loc_' + dev].value;
	}
	aDevice = new Device();
	aDevice.name = deviceName;
	aDevice.location = deviceLocation;
	aDevice.tag = 'dev_'+ dev;
	arrLength = listOfDevices.length;
	listOfDevices[arrLength] = aDevice;
	deviceFilled = true;
      }
    }
  }
  return deviceFilled;
}


//
// getListOfInterfaces()
// Function that retrieves all the devicesinterfaces known to the network and
// fills the list of interfaces that will be used to generate the NDL file
//
function getListOfInterfaces()
{
  listOfInterfaces = new Array();
  for (dev = 0 ; dev < listOfDevices.length; dev++){
    thisDevice = listOfDevices[dev];
    thisDevice.interfaces.length = 0;
    for (intf =0; intf <listOfInterfacesPerDevice[dev]; intf++){
      interfaceName = document.glif_form.elements[thisDevice.tag+'_intf_'+intf].value;
      var ifTypeIndex = document.glif_form.elements[thisDevice.tag+'_intf_'+intf +'_interfaceType'].options.selectedIndex;
      interfaceType = document.glif_form.elements[thisDevice.tag+'_intf_'+intf +'_interfaceType'].options[ifTypeIndex].value;
      var connTypeIndex = document.glif_form.elements[thisDevice.tag+'_intf_'+intf +'_connType'].options.selectedIndex;
      interfaceConnectionType = document.glif_form.elements[thisDevice.tag+'_intf_'+intf +'_connType'].options[connTypeIndex].value;
      interfaceConnection = document.glif_form.elements[thisDevice.tag+'_intf_'+intf +'_connection'].value;
      interfaceSeeAlso = document.glif_form.elements[thisDevice.tag+'_intf_'+intf +'_seeAlso'].value;
      interfaceCapacity = document.glif_form.elements[thisDevice.tag+'_intf_'+intf + '_capacity'].value;
      if( interfaceName != ""){
	arrLength = thisDevice.interfaces.length;
	thisDevice.interfaces[arrLength] = thisDevice.name + ':'+ interfaceName;
	anInterface = new Interface();
	anInterface.name = thisDevice.name + ':'+ interfaceName;
	anInterface.interfaceType = interfaceType;
	if(interfaceConnection != ""){
	  anInterface.connection = interfaceConnection;
	  anInterface.connectionType = interfaceConnectionType;
	}
	if(interfaceSeeAlso != ""){
	  anInterface.seeAlso = interfaceSeeAlso;
	}
	if(interfaceType == 'OC12Interface'){
	   anInterface.capacity = '7.776E+07';
        }	
        else if(interfaceType == 'OC48Interface'){
	   anInterface.capacity = '3.110E+08';
        }	
        else if (interfaceType == 'OC192Interface'){
	   anInterface.capacity = '1.244E+09';
        }	
	else if (interfaceCapacity != ""){
	  anInterface.capacity = interfaceCapacity;
	}
        
	interfaceLength = listOfInterfaces.length;
	listOfInterfaces[interfaceLength] = anInterface;
      }
    }
  }
}

//
// addCol()
// Helper function that add columns to a table
//
function addCol(html) {
  var td=document.createElement('td');
  td.innerHTML=html;
  return td;
}

//
// generate():
// Function associated with the "Generate NDL" button on the HTML form
//
function generate()
{
  getListOfDevices();
  getListOfInterfaces();
  if (validateLocations() && validateDevices())
    {
      ndl = document.glif_form.ndlfile;
      beginNDL();
      writeLocation();
      writeDeviceList();
      writeInterfaceList();
      endNDL();
    }
}

//
// validateLocations():
// Function that validates that all the necessary inputs for the
// locations have been provided.
//
function validateLocations(){
  isLocValid = true;
  msg = '';

  locationList = new Array();
  for (loc = 0; loc < gCurrentNumberOfLocations; loc++){
    aLocation = new Location();
    if(document.glif_form.elements['location_id_' + loc].value !=''){
      aLocation.id = document.glif_form.elements['location_id_' + loc].value;
    }
    if (document.glif_form.elements['location_name_' + loc].value != ''){
      aLocation.name = document.glif_form.elements['location_name_' + loc].value;
    }
    if(document.glif_form.elements['location_lat_' + loc].value !=  ''){
      aLocation.lat = document.glif_form.elements['location_lat_' + loc].value;
    }
    if(document.glif_form.elements['location_long_' + loc].value != ''){
      aLocation.longit = document.glif_form.elements['location_long_' + loc].value;
    }
    locPosition = locationList.length;
    if (aLocation.id != undefined || aLocation.name != undefined || aLocation.lat != undefined || aLocation.longit != undefined){
      locationList[locPosition] = aLocation;
    }
  }

  if (locationList.length == 0 ){
	isLocValid = false;
	alert('You have not specified any locations for this NDL file');
	return isLocValid;
  }

  for (l = 0; l < locationList.length; l++){
    if (locationList[l].id == undefined){
      isLocValid = false;
      msg = msg + '- location id'  + '\n';
    }
    if (locationList[l].name == undefined){
      isLocValid = false;
      msg = msg + '- location name'  + '\n';
    }
    if (locationList[l].lat == undefined){
      isLocValid = false;
      msg = msg + '- location lat'  + '\n';
    }
    if (locationList[l].longit == undefined){
      isLocValid = false;
      msg = msg + '- location long'  + '\n';
    }
  }  
  if (!isLocValid){
    alert('One of the locations you specified' + '\n' + 'is missing required fields:' +  '\n' + msg);
  }
  return isLocValid;
}

//
// validateDevices():
// Function that validates that all the necessary inputs for the
// devices have been provided.
//
function validateDevices(){
  isDevValid = true;
  msg = '';
  for (dev =0; dev < listOfDevices.length; dev++){
    thisDevice = listOfDevices[dev];
    if (thisDevice.location == undefined){
      isDevValid = false;
      msg = msg + ' Device ' + thisDevice.name + ' misses locations id' + '\n';
    }
  }
  if (!isDevValid){
    deviceFilled = false;
    alert(msg);
  }
  return isDevValid;
}

//
// beginNDL():
// Function that writes out the beginning part of the NDL file
//
function beginNDL()
{
  ndl.value = '<?xml version="1.0" encoding="UTF-8"?>' + '\n';
  ndl.value += '<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"' + '\n';
  ndl.value += '         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#\"' + '\n';
  ndl.value += '         xmlns:ndl=\"http://www.science.uva.nl/research/sne/ndl#\"' + '\n';
  ndl.value += '         xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">' + '\n\n';
}

//
// endNDL():
// Function that writes out the end part of the NDL file
//
function endNDL()
{
  ndl.value += '</rdf:RDF>';
}

//
// writeLocation():
// Function that writes out the NDL portion related to the network
// location
//
function writeLocation()
{

  for (l = 0; l < locationList.length; l++){
    ndl.value += '<!-- Description of ' + locationList[l].id + '-->' + '\n';
    ndl.value += '<ndl:Location rdf:about=\"#' + locationList[l].id + '\">' + '\n';
    ndl.value += '  <rdfs:label>' + locationList[l].name  +'</rdfs:label>' + '\n';
    ndl.value += '  <geo:lat>' + locationList[l].lat  +'</geo:lat>' + '\n';
    ndl.value += '  <geo:long>' + locationList[l].longit  +'</geo:long>' + '\n';
    ndl.value += '</ndl:Location>' +'\n\n';
  }
}


//
// writeDeviceList():
// Function that writes the NDL portion related to the devices present
// in the network
//
function writeDeviceList()
{
  for (dev =0; dev < listOfDevices.length; dev++){
    thisDevice = listOfDevices[dev];
    ndl.value += '<!--' + thisDevice.name + '-->' + '\n';
    ndl.value += '<ndl:Device rdf:about=\"#' + thisDevice.name + '\"' + '>' + '\n';
    ndl.value += '  <rdfs:label>' +  thisDevice.name + '</rdfs:label>' +'\n';
    ndl.value += '  <ndl:locatedAt rdf:resource=\"#' +  thisDevice.location + '\"/>' +'\n';
    if (thisDevice.interfaces.length >=0){
      for (intf =0; intf<thisDevice.interfaces.length; intf++){
	ndl.value += '  <ndl:hasInterface rdf:resource=\"#' + thisDevice.interfaces[intf] + '\"/>'+'\n';
      }
    }
    ndl.value += '</ndl:Device>' + '\n\n';
  }
}

//
// writeInterfaceList():
// Function that writes the NDL portion related to the interfaces in
// the network
//
function writeInterfaceList()
{
  for (intf=0; intf<listOfInterfaces.length;intf++){
    thisInterface = listOfInterfaces[intf];
    ndl.value += '<!--' + thisInterface.name + '-->' + '\n';
    ndl.value += '<ndl:Interface rdf:about=\"#' + thisInterface.name + '\"' + '>' + '\n';

    if (thisInterface.interfaceType == 'OC12Interface'){
	ndl.value += '<rdf:type rdf:resource=\"http://www.science.uva.nl/research/sne/ndl/tdm#OC12Interface\"/>' + '\n';
    }
    else if (thisInterface.interfaceType == 'OC48Interface'){
	ndl.value += '<rdf:type rdf:resource=\"http://www.science.uva.nl/research/sne/ndl/tdm#OC48Interface\"/>' + '\n';
    }
    else if (thisInterface.interfaceType == 'OC192Interface'){
	ndl.value += '<rdf:type rdf:resource=\"http://www.science.uva.nl/research/sne/ndl/tdm#OC192Interface\"/>' + '\n';
    }
    else if (thisInterface.interfaceType == 'EthernetInterface'){
	ndl.value += '<rdf:type rdf:resource=\"http://www.science.uva.nl/research/sne/ndl/ethernet#EthernetInterface\"/>' + '\n';
    }
    else if (thisInterface.interfaceType == 'IPInterface'){
	ndl.value += '<rdf:type rdf:resource=\"http://www.science.uva.nl/research/sne/ndl/ip#IPInterface\"/>' + '\n';
    }
    ndl.value += '  <rdfs:label>' +  thisInterface.name + '</rdfs:label>' +'\n';

    if (thisInterface.connection){
      if (thisInterface.seeAlso){
         ndl.value += '  <ndl:' + thisInterface.connectionType + ' rdf:resource=\"' + thisInterface.seeAlso + '\#' +  thisInterface.connection  + '\"/>' +'\n';
    } else{
      ndl.value += '  <ndl:' + thisInterface.connectionType + ' rdf:resource=\"#' +  thisInterface.connection + '\"/>' +'\n';
    	}
    }
    if (thisInterface.capacity){
      ndl.value += '  <ndl:capacity>' +  thisInterface.capacity + '</ndl:capacity>' +'\n';
    }
    ndl.value += '</ndl:Interface>' + '\n\n';	

  if (thisInterface.connection && thisInterface.seeAlso){
     ndl.value += '<!--' + thisInterface.seeAlso + '#' + thisInterface.connection + '-->' + '\n';
     ndl.value += '<ndl:Interface rdf:about="' + thisInterface.seeAlso + '#' +  thisInterface.connection + '\">' +'\n';
     ndl.value += '  <rdfs:seeAlso rdf:resource="' + thisInterface.seeAlso + '\"/>' + '\n';	
     ndl.value += '</ndl:Interface>' + '\n\n';
	}	
}
}

// Location:
// A definition for the Location object
//
function Location(id, name, lat,longit)
{
  this.id = id;
  this.name = name;
  this.lat = lat;
  this.longit = longit;
}

//
// Device:
// A definition for the Device object
//
function Device(name,location,tag)
{
  this.name = name;
  this.location = location;
  this.tag = tag;
  this.interfaces = new Array();
}

//
// Interface:
// A definition for the Interface object
//
function Interface(name,interfaceType,connectionType,connection,seeAlso,capacity)
{
  this.name = name;
  this.interfaceType = interfaceType;
  this.connectionType = connectionType;
  this.connection = connection;
  this.seeAlso = seeAlso;
  this.capacity = capacity;
}

function resetTables()
{
  removeInterfaceTables();
  document.forms[0].reset()
}


