
var width = document.getElementById("sequenceAlignment").clientWidth - 10;
var xoffset = 20;
var elementWidth = 1; //width/alignedResidues[0].length;

var vizOffset = d3.select("#vizOffset").append("svg")
                                    .attr("width", width-10)
                                    .attr("height", 10);

var sequenceAlignment = d3.select("#sequenceAlignment").append("svg")
                                    .attr("width", width-20)
                                    .attr("height", 100);

var BallColors = [];

//init sequenceAlignment ball colours, juxtaZoom 
function initShit(){
  for (var i = 0; i < proteins.length; i++) {
      BallColors[i] = ['green', 'red'];
      juxtaZoom[i] = [0, alignedSS[i].length];
  }
  globalZoom = [0, alignedSS[0].length];
}

function redrawD3(){
    sequenceAlignment.selectAll("*").remove();
    juxtaposition.selectAll("*").remove();
    superposition.selectAll("*").remove();

    initAtomDiffs();

    for (var i = 0; i < proteins.length; i++) {
        drawSequenceAlignment(i);
        drawJuxtaposition(i);
    }
    for (var i = 0; i < proteins.length; i++) {
        if(i!==reference)drawSuperposition(i);
    }
    drawSuperposition(reference);
}

function drawSequenceAlignment(n){

  sequenceAlignmentRects[n] = [];

  //console.log("Reqriting sequence alignment for protein num: " + n);

  sequenceAlignment.append("text")
          .attr("y", n*45 + 10)
          .attr("x", xoffset)
          .attr('text-anchor', 'left')
          .attr("class", "myLabel")
          .text(proteins[n]);

  var radialGradient = sequenceAlignment.append("defs")
    .append("radialGradient")
      .attr("id", "radial-gradient");

  radialGradient.append("stop")
      .attr("offset", "0%")
      .attr("stop-color", BallColors[n][0]);

  radialGradient.append("stop")
      .attr("offset", "100%")
      .attr("stop-color", "#fff");

  sequenceAlignment.append("circle")
          .attr("cx", xoffset/2)
          .attr("cy", n*45 + 25)
          .attr("r", 5)
          .attr("fill", "url(#radial-gradient)")//BallColors[n][0])
          .on("click", function(d) {
            var chain = Math.round((this.cy.animVal.value - 25)/45);
            viewer.get(proteins[chain]).setOpacity((BallColors[chain][0]==="green")? 0 : 1);
            viewer.requestRedraw();
            BallColors[chain] = [BallColors[chain][1], BallColors[chain][0]]
            radialGradient.select("stop").transition().attr("offset", "0%").attr("stop-color", BallColors[n][0]);
            d3.select(this).style("fill", "url(#radial-gradient)");
          });

  for (var i = 0; i < alignedResidues[n].length; i++) {
    var aminoacid = alignedResidues[n].charAt(i);
    var rect = sequenceAlignment.append("rect")
      .attr("height", 20)
      .attr("width", Math.round(elementWidth)+2)
      .attr("x", xoffset + Math.floor(i*elementWidth))
      .attr("y", 15 + n*45)
      .style("fill", function(d) {
           var returnColor;
           if(highlighted[n] - i === 0) {
              returnColor = "#66FF00";
           } else if(highlighted[n] - i < 4 && highlighted[n] - i > 0) {
              returnColor = blendColors("#66FF00", colorMolecule[n], (highlighted[n] - i) /4);
           } else if(highlighted[n] - i > -4 && highlighted[n] - i < 0) {
              returnColor = blendColors(colorMolecule[n], "#66FF00", 1-(Math.abs(highlighted[n] - i)) /4);
           } else if (aminoacid === '-') { returnColor = "lightgray";
           } else { returnColor = colorMolecule[n];}
           return returnColor;
       })
      .on("click", function(){
            var chain = Math.round((this.y.animVal.value - 15)/45);
            //console.log(chain);
            // console.log(proteins[chain]);
            var pos = sequenceAlignmentRects[chain].findIndex(x => x === this);
            //var pos = Math.round((this.x.animVal.value - 10)/(elementWidth * 0.95));
            if(alignedResidues[chain].charAt(pos) != '-'){
                if(highlighted[chain] === pos) {
                    highlighted[chain] = 9999;
                    //redrawD3Single(chain);
                    redrawD3();
                    resetViewerSelection(chain);
                } else {
                    highlighted[chain] = pos;
                    //redrawD3Single(chain);
                    redrawD3();
                    //this.style.fill == "#66FF00";
                    highlightPV(chain, alignToNotAlign[chain][pos]);
                }
            }
      });
      sequenceAlignmentRects[n][i] = rect._groups[0][0];     
  }

  if(juxtaZoom[n][0] !== 0 || juxtaZoom[n][1] !== alignedSS[n].length){
    var xPos = xoffset + juxtaZoom[n][0]*elementWidth;
    var length = xoffset + juxtaZoom[n][1]*elementWidth - xPos;

    var juxtaZoomGroup = sequenceAlignment.append("g")
    .attr("id", "handle")
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended)
    );

    //removal
    var quadPoints = (xPos+length - 4) + " " + (17 + n*45) + ", "
                        + (xPos+length - 6) + " " + (17 + n*45) + ", "
                        + (xPos+length - 20) + " " + (33 + n*45) + ", "
                        + (xPos+length - 18) + " " + (33 + n*45);

    juxtaZoomGroup.append("polygon")
              .attr("fill", "white")
              .style("opacity", 0.5)
              .attr("points", quadPoints); 

    quadPoints = (xPos+length - 4) + " " + (33 + n*45) + ", "
                        + (xPos+length - 6) + " " + (33 + n*45) + ", "
                        + (xPos+length - 20) + " " + (17 + n*45) + ", "
                        + (xPos+length - 18) + " " + (17 + n*45);

    juxtaZoomGroup.append("polygon")
              .attr("fill", "white")
              .style("opacity", 0.5)
              .attr("points", quadPoints); 

    juxtaZoomGroup.append("rect")
      .attr("height", 26)
      .attr("width", 24)
      .attr("x", xPos+length-24)
      .attr("y", 12 + n*45)
      .style("fill", "gray")
      .style("opacity", 0.5);

    //adjust juxtazoom
    juxtaZoomGroup.append("rect")
      .attr("height", 26)
      .attr("width", length - 22)
      .attr("x", xPos-1)
      .attr("y", 12 + n*45)
      .style("fill", "gray")
      .style("opacity", 0.5)
      .style('cursor', 'move');

      var dragCurrent = 0;
      var lastDrag = 0;
      var initStart  = juxtaZoom[n][0];
      var initEnd = juxtaZoom[n][1];
    

    function dragstarted(d) {
      //dragCurrent = 0;
      // var lastDrag;
      // var initStart;
      // var initEnd ;
    }
    function dragged(d) {
      dragCurrent += d3.event.dx;
      //console.log(xPos+length+dragCurrent);
      if((xPos+dragCurrent) >=xoffset-1 && Math.round((xPos+length+dragCurrent)/elementWidth) < alignedSS[n].length+1) 
        d3.select(this).attr("transform", "translate(" + dragCurrent + "," + 0 + ")");
      
      if(Math.abs(dragCurrent-lastDrag)>5){
        // console.log(dragCurrent);

        var dragedPosStart = Math.round(juxtaZoom[n][0]-(lastDrag - dragCurrent)/elementWidth);
        var dragedPosEnd = Math.round(juxtaZoom[n][1]-(lastDrag - dragCurrent)/elementWidth);

        if(dragedPosStart < 0) {
          dragedPosStart = 0;
          dragedPosEnd = initEnd - initStart;
        }
        if(dragedPosEnd > alignedSS[n].length) {
          dragedPosEnd = alignedSS[n].length;
          dragedPosStart = alignedSS[n].length - (initEnd - initStart);
        }

        juxtaZoom[n] = [Math.floor(dragedPosStart), Math.floor(dragedPosEnd)];
        juxtaposition.selectAll("*").remove();
        for (var i = 0; i < proteins.length; i++) {
          drawJuxtaposition(i);
        }

        lastDrag = dragCurrent;
      }


    }

    function dragended(d) {
      if(dragCurrent === 0) {
        //delete zoom
        juxtaZoom[n]=[0, alignedSS[n].length];
      } else {
        // var dragedPos0 = Math.round(initStart+dragCurrent/elementWidth);
        // var dragedPos1 = Math.round(initEnd+dragCurrent/elementWidth);
        // if((xPos+dragCurrent) < xoffset) {
        //   dragedPos0 = 0;
        //   dragedPos1 = juxtaZoom[n][1] - juxtaZoom[n][0];
        // }
        // if(Math.round((xPos+length+dragCurrent)/elementWidth) > alignedSS[n].length) {
        //   dragedPos1 = alignedSS[n].length;
        //   dragedPos0 = alignedSS[n].length - (juxtaZoom[n][1] - juxtaZoom[n][0]);
        // }

        // juxtaZoom[n] = [Math.floor(dragedPos0), Math.floor(dragedPos1)];
      }
      redrawD3();
    }

    // var juxtaAdjustGroup = sequenceAlignment.append("g")
    //   .attr("id", "handle");

    // //left adjust zoom
    // juxtaZoomGroup.append("rect")
    //   .attr("height", 26)
    //   .attr("width", 3)
    //   .attr("x", xPos-3)
    //   .attr("y", 12 + n*45)
    //   .style("fill", "#bfbfbf")
    //   // .style("opacity", 0.0)
    //   .style('cursor', 'ew-resize')
    //   .call(d3.drag()
    //       .on("start", dragstarted)
    //       .on("drag", leftDragged)
    //       .on("end", leftDragended)
    //   );

    // //right adjust zoom
    // juxtaZoomGroup.append("rect")
    //   .attr("height", 26)
    //   .attr("width", 3)
    //   .attr("x", xPos+length-1)
    //   .attr("y", 12 + n*45)
    //   .style("fill", "#bfbfbf")
    //   // .style("opacity", 0.0)
    //   .style('cursor', 'ew-resize')
    //   .call(d3.drag()
    //       .on("start", dragstarted)
    //       .on("drag", rightDragged)
    //       .on("end", rightDragended)
    //   );

    // var leftDragCurrent = 0;
    // function leftDragged(d){
    //   leftDragCurrent += d3.event.dx;

      
    //   console.log(this.parentNode)
    //   d3.select(this.parentNode).attr("transform", "scale(1." + leftDragCurrent + " 0)");
    // }

    // function leftDragended(d){}

    // function rightDragged(d){}

    // function rightDragended(d){}



  }

  //Draw Global zoom bar
  if(n === (proteins.length-1)){
    var dragStart = 0;
      globalZoom = [-1, alignedSS[n].length+1];
      var numOfZooms = 0;

      juxtaZoom.forEach(function(element){
          if(element[0]!=0 || element[1]!=alignedSS[n].length){
          numOfZooms++;
          if(globalZoom[0] > element[0] || globalZoom[0] === -1) globalZoom[0] = element[0];
          if(globalZoom[1] < element[1] || globalZoom[1] === alignedSS[n].length+1) globalZoom[1] = element[1];
          // console.log(globalZoom[0]);
        }
      });

      var xPos = xoffset + globalZoom[0]*elementWidth;
      var length = xoffset + globalZoom[1]*elementWidth - xPos;

      if(numOfZooms > 1){

        var globalZoomGroup = sequenceAlignment.append("g")
          .attr("id", "handle")
          .call(d3.drag()
              .on("start", dragstarted)
              .on("drag", globalDragged)
              .on("end", globalDragended)
          );

        globalZoomGroup.append("rect")
          .attr("height", 10)
          .attr("width", length+1)
          .attr("x", xPos-1)
          .attr("y", 50 + n*45)
          .style("fill", "gray")
          .style("opacity", 0.5);


        var quadPoints = (xPos+length - 1) + " " + (51 + n*45) + ", "
                      + (xPos+length - 2) + " " + (51 + n*45) + ", "
                      + (xPos+length - 9) + " " + (59 + n*45) + ", "
                      + (xPos+length - 8) + " " + (59 + n*45);

        globalZoomGroup.append("polygon")
                  .attr("fill", "white")
                  .style("opacity", 0.5)
                  .attr("points", quadPoints); 

        quadPoints = (xPos+length - 9) + " " + (51 + n*45) + ", "
                      + (xPos+length - 8) + " " + (51 + n*45) + ", "
                      + (xPos+length - 1) + " " + (59 + n*45) + ", "
                      + (xPos+length - 2) + " " + (59 + n*45);

        globalZoomGroup.append("polygon")
                  .attr("fill", "white")
                  .style("opacity", 0.5)
                  .attr("points", quadPoints); 

        var globalDragCurrent = 0;
        var globalLastDrag = 0;
        var globalInitStart  = globalZoom[0];
        var globalInitEnd = globalZoom[1];

        function globalDragged(d) {
          globalDragCurrent += d3.event.dx;
          //console.log(xPos+length+dragStart);
          if((xPos+globalDragCurrent) >= xoffset && Math.round((xPos+length+globalDragCurrent-xoffset)/elementWidth) < alignedSS[n].length) 
            d3.selectAll("#handle").attr("transform", "translate(" + globalDragCurrent + "," + 0 + ")");
        
          if(Math.abs(globalDragCurrent-globalLastDrag)>5){

            var dragedPosStart = Math.round(globalZoom[0]-(globalLastDrag - globalDragCurrent)/elementWidth);
            var dragedPosEnd = Math.round(globalZoom[1]-(globalLastDrag - globalDragCurrent)/elementWidth);

            if(dragedPosStart < 0) {
              dragedPosStart = 0;
              dragedPosEnd = globalInitEnd - globalInitStart;
            }
            if(dragedPosEnd > alignedSS[n].length) {
              dragedPosEnd = alignedSS[n].length;
              dragedPosStart = alignedSS[n].length - (globalInitEnd - globalInitStart);
            }

            globalZoom = [dragedPosStart, dragedPosEnd];

            juxtaZoom.forEach(function(element){

              if(element[0]!==0 || element[1]!==alignedSS[n].length){

                var element0 = Math.round(element[0]-(globalLastDrag - globalDragCurrent)/elementWidth);
                var element1 = Math.round(element[1]-(globalLastDrag - globalDragCurrent)/elementWidth);

                if(element0 < 0) {
                  element0 = 0;
                  element1 = element[1] - element[0];
                }
                if(element1 > alignedSS[n].length) {
                  element1 = alignedSS[n].length;
                  element0 = alignedSS[n].length - (element[1] - element[0]);
                }

                element[0] = element0;
                element[1] = element1;

              }
            });

            juxtaposition.selectAll("*").remove();
            for (var i = 0; i < proteins.length; i++) {
              drawJuxtaposition(i);
            }

            superposition.selectAll("*").remove();
            for (var i = 0; i < proteins.length; i++) {
                if(i!==reference)drawSuperposition(i);
            }
            drawSuperposition(reference);

            globalLastDrag = globalDragCurrent;

          }


        }

        function globalDragended(d) {
          if(globalDragCurrent === 0) {
            juxtaZoom.forEach(function(element){
                element[0] = 0;
                element[1] = alignedSS[n].length;
            });
            globalZoom = [0, alignedSS[n].length];

          } else {
            // juxtaZoom.forEach(function(element){

            //   if(element[0]!==0 || element[1]!==alignedSS[n].length){

            //     var element0 = Math.round(element[0]+globalZoomOffset/elementWidth);
            //     var element1 = Math.round(element[1]+globalZoomOffset/elementWidth);
            //     if(element0 < 0) {
            //       element0 = 0;
            //       element1 = element[1] - element[0];
            //     }
            //     if(element1 > alignedSS[n].length) {
            //       element1 = alignedSS[n].length;
            //       element0 = alignedSS[n].length - (element[1] - element[0]);
            //     }

            //     element[0] = element0;
            //     element[1] = element1;

            //   }
            // });
          }

          redrawD3();
        }
      } else {
        globalZoom = [0, alignedSS[n].length];
      }
      
    }

    addSelection(sequenceAlignment, n, elementWidth, 20);
  }

  function initAtomDiffs(){
    for (var chain = 0; chain < proteins.length; chain++) {
      atomDiffs[chain] = [];
      if(chain !== reference){
        for (var i = 0; i < alignedSS[chain].length-1; i++) {
          if (alignedSS[chain].charAt(i) != '-' && alignedSS[reference].charAt(i) != '-'){
            var v1 = atoms[chain][alignToNotAlign[chain][i]]._bB;
            var v2 = atoms[reference][alignToNotAlign[reference][i]]._bB;

            var dx = v1[0] - v2[0];
            var dy = v1[1] - v2[1];
            var dz = v1[2] - v2[2];

            atomDiffs[chain][i] = (Math.sqrt( dx * dx + dy * dy + dz * dz ));

          }
        }
      }
    }
  }

  function blendColors(c0, c1, p) {
      var f=parseInt(c0.slice(1),16),t=parseInt(c1.slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF,R2=t>>16,G2=t>>8&0x00FF,B2=t&0x0000FF;
      return "#"+(0x1000000+(Math.round((R2-R1)*p)+R1)*0x10000+(Math.round((G2-G1)*p)+G1)*0x100+(Math.round((B2-B1)*p)+B1)).toString(16).slice(1);
  }