.packageName <- "ChromoViz"
"cViz" <-
function(featureSet, bandPosFile)
{
  ### CHROMOSOME LIST
  chromList <- cViz.distinctNames(bandPosFile$chrom)
  lenOfChromList <- length(chromList)

   for(i in 1:lenOfChromList){
#  for(i in 20:20){
     theChrom <- chromList[i]

     ### FRAME DESIGN
     frameDesign <- list()
     frameDesign$height <- 2.5
     frameDesign$top <- 1.5
     frameDesign$bottom <- 1
     frameDesign$cex <- 0.7
     frameDesign$interval <- 0.5
     frameDesign$imgFileWidth <- 800 / 80
     
     frameDesign$imgFileHeight <- 150 / 80
     frameDesign$mai <- c(0.1, 0.1, 0.1, 0.1)

     ### PARSE bandPosFile
     eachChr <- subset(bandPosFile, chrom == theChrom)
 
     ### DRAW CHROMOSOME
     cViz.drawChr(eachChr,  theChrom, frameDesign)

     ### ADJUST THE FRAME DESIGN
     frameDesign$height <- 2.5
     frameDesign$top <-  2
     frameDesign$bottom <- 1
     frameDesign$imgFileHeight <- 50 / 80

     ### DRAW PRIMARY FEATURES
     trackList <- cViz.drawFeature(featureSet, eachChr, theChrom, frameDesign)
      
     ### CHROMOSOMAL WRAPPER HTML
     cViz.makeChromWrapperHtml(theChrom, trackList)
  }
  
  ### MERGE SVG files
  for(i in 1:lenOfChromList){
#   for(i in 20:20) {  
  
     theChrom <-  chromList[i]
     chrSVGFile <- paste(theChrom, "svg", sep=".")          
     pat <- paste(theChrom, ".+.(\.svg$)", sep="")
     otherSVGFileList <- list.files(path=".", pattern=pat)     
     outFile <- paste("merged", chrSVGFile, sep=".")

     ### ROOTNODE, LOAD A FILE
     cViz.mergeSVG(chrSVGFile, otherSVGFileList, outFile)
        
     ### DELETE INDIVIDUAL svg FILES        
     otherSVGFileList <- append(otherSVGFileList, chrSVGFile)
#     unlink(otherSVGFileList)     
  }   

  ### HEADER HTML
  cViz.makeHeaderHtml("header")

  ### FRAME HTML
  cViz.makeFrameHtml("index", chromList[1])
  
  ### JAVASCRIPT FILE TO CONTROL SVG
  data(svgControl)
  write(svgControl, file="control.js")
}
"cViz.addAnnoNodes2SVG" <-
function(svgFile, curGid, theItems) {
    inFile <- xmlTreeParse(svgFile)
    curNode <- inFile$doc$children$svg
    
    ### CREATE ancestor NODE 
    ancestorAttrs <- xmlAttrs(curNode)
    ### INSERT NAMESPACE INFORMATION
    ancestorAttrs <- append(ancestorAttrs, "http://www.w3.org/1999/xlink")
    names(ancestorAttrs)[length(ancestorAttrs)] <- "xmlns\:xlink"
    ancestorNode <- xmlNode("svg", attrs=ancestorAttrs)
      
    ### CREATE g NODE
    rootNode <-  xmlNode("g", attrs=c(id=curGid))
    
    ### COPY CHILDREN to THE root NODE
    childList <- xmlChildren(curNode)
    childListName <- names(childList)
    childNodeNum <- xmlSize(childList)   
    for(j in 3:childNodeNum) {
        if(childListName[j] == "rect") {
           childList[[j]] <- cViz.insertNewAttrValue(childList[[j]],
                            "id",  theItems[j-2]) 
        }            
        rootNode <- append.XMLNode(rootNode, childList[[j]])
    }
    ancestorNode <- append.XMLNode(ancestorNode, rootNode )
    
    ### APPEND use NODE to THE root NODE
    useAttrs <- c(id=paste(curGid, "1", sep="\_"), info=0,
                  "xlink\:href"=paste("\#",curGid, sep=""),
                  transform="translate(0,0)", x="0", y="0",
                  style="stroke-opacity:.4", visibility="hidden")
    useNode <- xmlNode("use", attrs=useAttrs)    
    ancestorNode <- append.XMLNode(ancestorNode, useNode)
            
    ### WRITE INTO A FILE     
    fileHeader <- "\<?xml version=\"1.0\" standalone=\"yes\"?\>"
    fileContents <- paste(fileHeader, toString(ancestorNode), sep="")       
    cat(fileContents, file=svgFile, append=F)                      
    #cat(toString(ancestorNode), file=svgFile, append=F)
}
"cViz.addZeroToTheSingleDigit" <-
function(vec)
{
   idx <- grep("^chr[1-9]$|^chr[1-9]_" ,  vec, perl = TRUE) 
   vec[idx] <- sub("chr", "chr0", vec[idx])
   vec
}
"cViz.distinctNames" <-
function(v1) {
      names( table(v1))
}
"cViz.drawChr" <-
function(eachChr, chrom, frameDesign) {
  len <- length(eachChr$begin)
  top <-  frameDesign$top
  bottom <- frameDesign$bottom
  cex <- frameDesign$cex
  interval <- frameDesign$interval
 
  ### SET STANING 
  eachChr$shadeCol <- rep("", len)
  for(i in 1:len) {
    if(eachChr$stain[i] == "acen")         eachChr$shadeCol[i] <- "skyblue2"
    else if(eachChr$stain[i] == "gneg")    eachChr$shadeCol[i] <- "gray92"
    else if(eachChr$stain[i] == "gpos25")  eachChr$shadeCol[i] <- "gray75"
    else if(eachChr$stain[i] == "gpos50")  eachChr$shadeCol[i] <- "gray60"
    else if(eachChr$stain[i] == "gpos75")  eachChr$shadeCol[i] <- "gray45"
    else if(eachChr$stain[i] == "gpos100") eachChr$shadeCol[i] <- "gray30"
    else if(eachChr$stain[i] == "gvar")   eachChr$shadeCol[i]  <- "khaki2"
    else  eachChr$shadeCol[i] <- "brown"   ### stalk
  }

  ### PREPARE FRAME
  devSVG(file=paste(chrom, "svg", sep="."), 
        width = frameDesign$imgFileWidth,  height =frameDesign$imgFileHeight)

#  png(file=paste(chrom, "png", sep="."), 
#          width=frameDesign$imgFileWidth, height=frameDesign$imgFileHeight) 
  par(mai=frameDesign$mai)
  plot(c(0, 0), c(0, frameDesign$height), type="n",  xlim=c(0, max(eachChr$end)*1.1),  
            axes=F,  xlab="", ylab="" )        

  ### DRAW BANDS WITH ALTERNATING SHADING
  for(i in 1:len) {
     if( eachChr$stain[i] != "acen") {
     if( i%%2 == 1) {
             rect( eachChr$begin[i], bottom, eachChr$end[i], top, 
                    border=eachChr$shadeCol[i],  col=eachChr$shadeCol[i])
             text( (3*eachChr$begin[i] + eachChr$end[i])/4 ,  bottom-interval , 
               pos=1, labels=eachChr$band[i], srt=90, cex=cex)
         } else {
             rect( eachChr$begin[i], bottom, eachChr$end[i], top, 
                    border=eachChr$shadeCol[i],  col=eachChr$shadeCol[i])
             text( (3*eachChr$begin[i] + eachChr$end[i])/4 , top+interval, 
               pos=3, labels=eachChr$band[i], srt=90, cex=cex) 
         }
     }
  }

  ### DRAW CENTROMERES
  i <- 1
  while(eachChr$stain[i] != "acen") {
     i <- i + 1
  }
  ### LEFT CENTROMERE
  leftCenX <- c(eachChr$begin[i], eachChr$end[i], eachChr$begin[i])
  leftCenY <- c(bottom, (bottom+top)/2 , top)
  polygon(leftCenX, leftCenY, border=eachChr$shadeCol[i],  col=eachChr$shadeCol[i])
  ### RIGHT CENTROMERE
  i <- i + 1
  rightCenX <- c(eachChr$begin[i], eachChr$end[i], eachChr$end[i])
  rightCenY <- c((bottom+top)/2, bottom, top)
  polygon(rightCenX, rightCenY, border=eachChr$shadeCol[i], col=eachChr$shadeCol[i])
  mtext(text=chrom, side=4, at=c(max(eachChr$end)*1.05, (top+bottom)/2), 
           las=2, adj=1,  cex=cex)
 
  dev.off()
}
"cViz.drawFeature" <-
function (inFile, eachChr, theChrom, frameDesign)
{
  ### SET FRAME DESIGN PARAMETERS
  top <-  frameDesign$top
  bottom <- frameDesign$bottom
  cex <- frameDesign$cex

  ### SELECT FEATURE
  distinctNames <- sort( cViz.distinctNames(inFile$track)  )  
  lenOfDistinctNames <- length(distinctNames)

  ### CHOOSE NAMES ONLY WITH VALUES FROM THE distinctNames
  chosenDistinctNames <- vector()

  itemList <- list()
  for(j in 1:lenOfDistinctNames) {
      subChunk <- subset(inFile, 
               (track == distinctNames[j] ) & (chrom == theChrom) & (value != 0.0)) 
    
      if(length(subChunk$track) > 0) {
          chosenDistinctNames <- append(chosenDistinctNames, distinctNames[j])
         
          ### item 
          ###   example) accession number
          itemList[[j]] <- as.vector(subChunk$item)
          
          pngFileName <- paste(theChrom, distinctNames[j],  sep=".")

          ### PREPARE FRAME
          svgFile <- paste(pngFileName, "svg", sep=".")
          devSVG(file=svgFile,   width = frameDesign$imgFileWidth,  
                 height=frameDesign$imgFileHeight)

#   png(file=paste(pngFileName, "png", sep="."), 
#         width=frameDesign$imgFileWidth, height=frameDesign$imgFileHeight)
          par(mai=frameDesign$mai)
          plot(c(0, 0), c(0, frameDesign$top), type="n",  xlim=c(0, max(eachChr$end)*1.1),  
               axes=F,  xlab="", ylab="" ) 

          ### VALUE
          len <- length(subChunk$begin)
          scale <- (top-bottom)/max(abs(subChunk$value))
          for(k in 1:len) {
             rect( subChunk$begin[k], bottom,
                   subChunk$end[k],  bottom+subChunk$value[k]*scale,
                   border="orangered", col="orangered")
#       rect( subChunk$begin[k], bottom,
#          subChunk$begin[k],  bottom+subChunk$value[k]*scale,
#               border="orangered", col="orangered")
          }  
          lines( c(min(eachChr$begin),  max(eachChr$end)), c(bottom, bottom), col="gray") 
          mtext(text=subChunk$track[len], side=4, at=c(max(eachChr$end)*1.05, bottom), 
                las=2, adj=1, font=1, cex=cex)
          dev.off()
    
          ### APPEND ANNOTATION NODES TO THE SVG NODE
          curGid <- distinctNames[j]
          cViz.addAnnoNodes2SVG(svgFile, curGid, itemList[[j]])                 
      }
  } # THE END OF for LOOP 
  
  chosenDistinctNames
}
"cViz.getHeightOfPolylinePoints" <-
function(inFile)
{
svgTags <- xmlTreeParse(inFile)
targetNode <-  svgTags$doc$children$svg$children$g    
pointValues <- xmlAttrs(targetNode$children$polyline)[["points"]]
strsplit(pointValues, " ")[[1]][3]
}
"cViz.incPolylineAttrValue" <-
function(theNode, delta)
{ 
  theAttrName <- "points"
  attrNames <- names(xmlAttrs(theNode))
  attrValues <- as.vector(xmlAttrs(theNode))
  attrNumber <- length(attrNames)
  newAttrValues <- attrValues
  names(newAttrValues) <- attrNames

  for(i in 1:attrNumber){ 
  
    if(attrNames[i] == theAttrName) {
     
      strPoints <- strsplit(newAttrValues[i] , " ")[[1]]
      strPoints[3] <- as.numeric(strPoints[3]) + delta
      strPoints[6] <- as.numeric(strPoints[6]) + delta      
      newAttrValues[i] <- paste(strPoints[1], ",", strPoints[3], 
                         strPoints[4],  ",", strPoints[6], sep=" ")  
    }
  }
 
  attrVector <- attrValues
  names(attrVector) <- attrNames
  newNode <- xmlNode(xmlName(theNode), attrs=newAttrValues)
  newNode
}
"cViz.incSVGviewBoxValue" <-
function(theNode, delta)
{ 
  theAttrName <- "viewBox"
  attrNames <- names(xmlAttrs(theNode))
  attrValues <- as.vector(xmlAttrs(theNode))
  attrNumber <- length(attrNames)
  newAttrValues <- attrValues
  names(newAttrValues) <- attrNames

  for(i in 1:attrNumber){ 
  
    if(attrNames[i] == theAttrName) {
     
      strPoints <- strsplit(newAttrValues[i] , ",")[[1]]
      strPoints[4] <- as.numeric(strPoints[4]) + delta
      newAttrValues[i] <- paste(strPoints[1], strPoints[2], 
                                strPoints[3], strPoints[4], sep=",")  
    }
  }
 
  attrVector <- attrValues
  names(attrVector) <- attrNames
  newNode <- xmlNode(xmlName(theNode), attrs=newAttrValues)
  newNode
}
"cViz.incSingleAttrValue" <-
function(theNode, theAttrName, delta)
{
  attrNames <- names(xmlAttrs(theNode))
  attrValues <- as.vector(xmlAttrs(theNode))
  attrNumber <- length(attrNames)
  newAttrValues <- attrValues
  names(newAttrValues) <- attrNames

  for(i in 1:attrNumber){ 
    if(attrNames[i] == theAttrName) {
      newAttrValues[i] <- as.numeric(xmlAttrs(theNode)[[theAttrName]] )  + 
                          as.numeric(delta)
    }
  }
  
  attrVector <- attrValues
  names(attrVector) <- attrNames
  newNode <- xmlNode(xmlName(theNode), attrs=newAttrValues)
  newNode
}
"cViz.incTextAttrValue" <-
function(theNode, delta)
{ 
  theAttrName <- "transform"
  theXmlValue <- xmlValue(theNode)
  attrNames <- names(xmlAttrs(theNode))
  attrValues <- as.vector(xmlAttrs(theNode))
  attrNumber <- length(attrNames)
  newAttrValues <- attrValues
  names(newAttrValues) <- attrNames

  for(i in 1:attrNumber){ 
  
    if(attrNames[i] == theAttrName) {
                                  
      theTransform <- gsub("[a-z(,)]", " ", newAttrValues[i], perl=TRUE)
      theTransform <- strsplit(theTransform, " +")[[1]]
      theTransform[3] <- as.numeric(theTransform[3]) + delta
      newAttrValues[i] <- paste("translate(", theTransform[2], ",",
                             theTransform[3], ")  ", sep="")    
    }
  }
 
  attrVector <- attrValues
  names(attrVector) <- attrNames
  newNode <- xmlNode(xmlName(theNode), value=theXmlValue, attrs=newAttrValues)
  newNode
}
"cViz.insertNewAttrValue" <-
function(theNode, theAttrName, theAttrValue)
{
  newAttrValues <- as.vector(xmlAttrs(theNode))
  names(newAttrValues) <- names(xmlAttrs(theNode))

  newAttrValues <- append(newAttrValues, theAttrValue, after=0)
  names(newAttrValues)[1] <- theAttrName
  newNode <- xmlNode(xmlName(theNode), attrs=newAttrValues)
 
  newNode  
}
"cViz.loadFiles" <-
function(fileList)
{
   lenOfFileList <- length(fileList)
   if(lenOfFileList > 0) {
      result <- read.table(fileList[1], sep="\t", na.strings = "NA",  header=T, as.is=TRUE)
      result$chrom <- cViz.addZeroToTheSingleDigit(result$chrom)
 
      if(lenOfFileList > 1) {
         for(i in 2:lenOfFileList) {
            tempDataFrame <- read.table(fileList[i], sep="\t", 
                             na.strings = "NA",  header=T, as.is=TRUE)
            tempDataFrame$chrom <- cViz.addZeroToTheSingleDigit(tempDataFrame$chrom)
            result <- rbind(result, tempDataFrame)  
         }
      }
   }

   result <- subset(result, track != "NA")
}
"cViz.makeChromWrapperHtml" <-
function(theChrom, trackList)
{
   includeFile <- paste("merged", theChrom, "svg", sep=".")   
   ### OPEN AN HTML FILE 
   htmlOut <- file( paste(theChrom, ".html", sep=""), "w")

   ### INCLUDE CHROMOSOME
   cat("<HTML><HEAD>",file = htmlOut, sep="\n")
   cat("<script language=\"javascript1.2\" src=\"control.js\" type=\"text/javascript\">", 
          file=htmlOut, sep="\n") 
   cat("</script></HEAD><BODY>", file=htmlOut, sep="\n")     
   cat("<TABLE align=center><BR><TR><TD width=800 valign=\"top\">", 
             file=htmlOut, sep="\n")             
   cat("<embed name=\"Chromosome\"", file=htmlOut)
   cat(" width=\"800\" height=\"600\" src=\"", file=htmlOut)
   cat(includeFile, file = htmlOut)
   cat("\"></TD>", file = htmlOut, sep="\n")     
   cat("<TD width=\"200\" valign=\"top\"><FORM name=\"FindData\"><FONT size=\"2\">", 
             file = htmlOut, sep="\n")         
   cat("<input type=\"text\" name=\"accNum\" size=\"15\">", file = htmlOut, sep="\n")
   cat("<input type=\"button\" value=\"Search\" onClick=\"FindAccNum(\'Chromosome\')\;\"><br><br><br>",
         file = htmlOut, sep="\n")
      
   lenOfTrackList <- length(trackList)
   for(i in 1:lenOfTrackList ) {
        cat("<input type=\"checkbox\" name=\"", file = htmlOut)
        cat(paste(trackList[i], "1", sep="\_"), file = htmlOut)
        cat("\" unchecked onClick=\"MovetoZero(\'Chromosome\', this)\;\">",file = htmlOut, sep="\n")
        cat(trackList[i], file = htmlOut)
        cat("<br>", file = htmlOut, sep="\n")
   }
   cat("</FONT></FORM></TD></TR></TABLE>", file = htmlOut, sep="\n")
   cat("<BR></BODY></HTML>", file = htmlOut, sep="\n")

   ### CLOSE THE HTML FILE
   close(htmlOut)
}
"cViz.makeFrameHtml" <-
function(reportName, initMainPrefix)
{    
     htmlOut <- file( paste(reportName, "html",  sep="."),"w")
 
     cat("<HEAD><HEAD><TITLE>PAC:Paint Along Chromosom</TITLE></HEAD>", 
             file = htmlOut, sep="\n")
     cat("<FRAMESET rows=\"10%, 90%\" framespacing=0 border=0 frameborder=0>",
             file = htmlOut, sep="\n")
     cat("<FRAME NAME=\"header\"  scrolling=no  noresize target=\"main\" ",
             file = htmlOut)
     cat("src=\"header.html\" >",  file = htmlOut, sep="\n")
     cat("<FRAME NAME=\"main\"  scrolling=auto  noresize target=\"main\"  src=\"",
             file = htmlOut)
     cat( paste(initMainPrefix, "html", sep="."),  file = htmlOut)
     cat("\" ><NOFRAMES><BODY LINK=yellow VLINK=red ALINK=yellow></BODY>", 
            file = htmlOut, sep="\n")
     cat("</NOFRAMES><FRAMESET></HTML>",  file = htmlOut)      
  
    close(htmlOut)
}
"cViz.makeHeaderHtml" <-
function(fileName)
{  
   ### PREPARE INDIVIDUAL HTML 
   pat <- paste("chr", ".*.(\.html$)", sep="")
   reportList <- list.files(path = ".", pattern=pat ) 
   lenOfReportList <- length(reportList)

   ### OPEN AN HTML FILE
   htmlOut <- file( paste(fileName, "html", sep="."), "w")
   cat("<HTML><HEAD><TITLE>PAC Header</TITLE><BODY>", file = htmlOut, sep="\n")
   cat("<TABLE ALIGN=CENTER CELLPADDING=0 CELLSPACING=0><TR>", file = htmlOut, sep="\n")

   ### WRITE ONLY EXISING HTML FILES IN A CURRENT DIRECTORY
   for(i in 1:lenOfReportList) {
      cat("<td width=20><p align=center><a target=main a href=\"", file = htmlOut)
      cat( reportList[i], file = htmlOut)
      cat( paste("\">", 
           substr(reportList[i], 4, nchar(reportList[i])-5), sep=""), file = htmlOut)
      cat("</a></p></td>", file = htmlOut, sep="\n")
   }
   cat("</TR></TABLE></BODY></HTML>", file = htmlOut, sep="\n")

   ### CLOSE AN HTML FILE
   close(htmlOut)
}
"cViz.mergeSVG" <-
function(chromFile, trackFilesList, outFile)
{
    ### MAKE A CHROMOSOME NODE
    chromNode <- xmlTreeParse(chromFile)
    chromNodeSize <- xmlSize(xmlRoot(chromNode))

    ### GET height AND SAVE AS A delta
    curNode <- chromNode$doc$children$svg
    chrHeight <- as.numeric( xmlAttrs( curNode )[["height"]])
    trackFilesListNumber <- length(trackFilesList)
    tempChildNode <- xmlTreeParse(trackFilesList[1])$doc$children$svg
    delta <- as.numeric( xmlAttrs(tempChildNode)[["height"]])

    ### MAKE A ROOT NODE AND RESET height
    rootAttrs <- xmlAttrs( curNode )
    ### APPEND NAME SPACE
    rootAttrs <- append(rootAttrs, "http://www.w3.org/1999/xlink")
    names(rootAttrs)[length(rootAttrs)] <- "xmlns\:xlink"
    rootNode <- xmlNode("svg", attrs=rootAttrs ) 
    rootNode <- cViz.incSingleAttrValue(rootNode, 
                 "height", delta*trackFilesListNumber)          
    rootNode <- cViz.incSVGviewBoxValue(rootNode, 
                  delta*trackFilesListNumber)                   

    ### APPEND CHROMOSOMAL BAND NODES
    for(i in 1:chromNodeSize) {                    
       rootNode <- append.XMLNode(rootNode,  curNode[[i]])
    } 

    ### ATTACH OTHER TRACK FILES
    for(i in 1:trackFilesListNumber) { 
       moveDown <- chrHeight + i*delta       
       
       trackNode <- xmlTreeParse(trackFilesList[i], addAttributeNamespaces=T)
       useNode <- xmlRoot(trackNode)$children$use
       
       groupChildren <- xmlRoot(trackNode)$children$g
  
       ### CREATE NEW GROUP NODE
       newGroupNode <- xmlNode("g", attrs=xmlAttrs(groupChildren) )

       ### UPDATE GROUP CHILDREN height
       childList <- xmlChildren(groupChildren)
       childNames <- names(childList)
       tagNum <- xmlSize(groupChildren)
       newInfo <- 0
       
       for(j in 1:tagNum) {
           if(childNames[j] == "rect") {
                childList[[j]] <- cViz.incSingleAttrValue(childList[[j]], "y", moveDown) 
           }
           if(childNames[j] == "polyline") {
                childList[[j]] <- cViz.incPolylineAttrValue(childList[[j]], moveDown)
                newInfo <- strsplit(xmlAttrs(childList[[j]])[["points"]], " ")[[1]][3]                
           }    
           if(childNames[j] == "text") {
               childList[[j]] <- cViz.incTextAttrValue(childList[[j]], moveDown) 
           }               
           
           if((i==1) && (j==1)) {
               newInfo <- xmlAttrs(childList[[j]])[["y"]]
           }         
                    
           newGroupNode <- append.XMLNode(newGroupNode, childList[[j]])        
       }
    
       ### APPEND NEW GROUP NODE TO THE ROOT NODE
       rootNode <- append.XMLNode(rootNode, newGroupNode)
       
       ### APPEND use NODE TO THE ROOT NODE
       useNode <- xmlRoot(trackNode)$children$use
       useNode <- cViz.incSingleAttrValue(useNode, "info", newInfo)
       rootNode <- append.XMLNode(rootNode, useNode)
   }

   ### WRITE INTO A FILE
   file.create(outFile)
   write("<?xml version=\"1.0\"?>", file=outFile, append=F)   
   cat(toString(rootNode), file=outFile, append=T)                 
}
