drawIntermediateLayerAnnotation = (arg) => {
  let leftX = arg.leftX,
    curLayerIndex = arg.curLayerIndex,
    group = arg.group,
    intermediateGap = arg.intermediateGap,
    isFirstConv = arg.isFirstConv,
    i = arg.i;

  let kernelAnnotation = group.append('g')
    .attr('class', 'kernel-annotation');
  
  kernelAnnotation.append('text')
    .text('Kernel')
    .attr('class', 'annotation-text')
    .attr('x', leftX - 2.5 * kernelRectLength * 3)
    .attr('y', nodeCoordinate[curLayerIndex - 1][0].y + kernelRectLength * 3)
    .style('dominant-baseline', 'baseline')
    .style('text-anchor', 'end');

  let sliderX, sliderY, arrowSX, arrowSY, dr;
  let sliderX2, sliderY2, arrowSX2, arrowSY2, dr2, arrowTX2, arrowTY2;
  
  if (isFirstConv) {
    sliderX = leftX;
    sliderY = nodeCoordinate[curLayerIndex - 1][0].y + nodeLength +
      kernelRectLength * 3;
    arrowSX = leftX - 5;
    arrowSY = nodeCoordinate[curLayerIndex - 1][0].y + nodeLength +
      kernelRectLength * 3 + 5;
    dr = 20;

    sliderX2 = leftX;
      sliderY2 = nodeCoordinate[curLayerIndex - 1][1].y + nodeLength +
    kernelRectLength * 3;
    arrowSX2 = leftX - kernelRectLength * 3;
    arrowSY2 = nodeCoordinate[curLayerIndex - 1][1].y + nodeLength + 15;
    arrowTX2 = leftX - 13;
    arrowTY2 =  nodeCoordinate[curLayerIndex - 1][1].y + 15;
    dr2 = 35;
  } else {
    sliderX = leftX - 3 * kernelRectLength * 3;
    sliderY = nodeCoordinate[curLayerIndex - 1][0].y + nodeLength / 3;
    arrowSX = leftX - 2 * kernelRectLength * 3 - 5;
    arrowSY = nodeCoordinate[curLayerIndex - 1][0].y + nodeLength - 10;
    dr = 50;

    sliderX2 = leftX - 3 * kernelRectLength * 3;
    sliderY2 = nodeCoordinate[curLayerIndex - 1][2].y - 3;
    arrowTX2 = leftX - kernelRectLength * 3 - 4;
    arrowTY2 = nodeCoordinate[curLayerIndex - 1][2].y + kernelRectLength * 3 + 6;
    arrowSX2 = leftX - kernelRectLength * 3 - 13;
    arrowSY2 = nodeCoordinate[curLayerIndex - 1][2].y + 26;
    dr2 = 20;
  }

  let slideText = kernelAnnotation.append('text')
    .attr('x', sliderX)
    .attr('y', sliderY)
    .attr('class', 'annotation-text')
    .style('dominant-baseline', 'hanging')
    .style('text-anchor', isFirstConv ? 'start' : 'end');
  
  slideText.append('tspan')
    .style('dominant-baseline', 'hanging')
    .text('Slide kernel over input channel');

  slideText.append('tspan')
    .attr('x', sliderX)
    .attr('dy', '1em')
    .style('dominant-baseline', 'hanging')
    .text('to get intermediate result');

  // slideText.append('tspan')
  //   .attr('x', sliderX)
  //   .attr('dy', '1em')
  //   .style('dominant-baseline', 'hanging')
  //   .text('');

  slideText.append('tspan')
    .attr('x', sliderX)
    .attr('dy', '1.2em')
    .style('dominant-baseline', 'hanging')
    .style('font-weight', 700)
    .text('Click ');
  
  slideText.append('tspan')
    .style('dominant-baseline', 'hanging')
    .style('font-weight', 400)
    .text('to learn more')

  drawArrow({
    group: group,
    tx: leftX - 7,
    ty: nodeCoordinate[curLayerIndex - 1][0].y + nodeLength / 2,
    sx: arrowSX,
    sy: arrowSY,
    hFlip: !isFirstConv,
    dr: dr,
    marker: 'marker'
  });

  // Add kernel annotation
  let slideText2 = kernelAnnotation.append('text')
    .attr('x', sliderX2)
    .attr('y', sliderY2)
    .attr('class', 'annotation-text')
    .style('dominant-baseline', 'hanging')
    .style('text-anchor', isFirstConv ? 'start' : 'end');

  slideText2.append('tspan')
    .style('dominant-baseline', 'hanging')
    .text('Each input chanel');

  slideText2.append('tspan')
    .attr('x', sliderX)
    .attr('dy', '1em')
    .style('dominant-baseline', 'hanging')
    .text('gets a different kernel');

  slideText2.append('tspan')
    .attr('x', sliderX)
    .attr('dy', '1.3em')
    .style('font-weight', 700)
    .style('dominant-baseline', 'hanging')
    .text('Hover over ');

  slideText2.append('tspan')
    .style('font-weight', 400)
    .style('dominant-baseline', 'hanging')
    .text('to see value!')

  drawArrow({
    group: group,
    tx: arrowTX2,
    ty: arrowTY2,
    sx: arrowSX2,
    sy: arrowSY2,
    dr: dr2,
    hFlip: !isFirstConv,
    marker: 'marker'
  });


  // Add annotation for the sum operation
  let plusAnnotation = group.append('g')
    .attr('class', 'plus-annotation');
  
  let intermediateX2 = leftX + 2 * nodeLength + 2.5 * intermediateGap;
  let textX = intermediateX2;
  let textY = nodeCoordinate[curLayerIndex][i].y + nodeLength +
      kernelRectLength * 3;
  
  // Special case 1: first node
  if (i === 0) { textX += 30; }

  // Special case 2: last node 
  if (i === 9) {
    textX = intermediateX2 + plusSymbolRadius - 10;
    textY -= 2.5 * nodeLength;
  }

  let plusText = plusAnnotation.append('text')
    .attr('x', textX)
    .attr('y', textY)
    .attr('class', 'annotation-text')
    .style('dominant-baseline', 'hanging')
    .style('text-anchor', 'start');
  
  plusText.append('tspan')
    .style('dominant-baseline', 'hanging')
    .text('Add up all intermediate');
  
  plusText.append('tspan')
    .attr('x', textX)
    .attr('dy', '1em')
    .style('dominant-baseline', 'hanging')
    .text('results and then add bias');
  
  if (i === 9) {
    drawArrow({
      group: group,
      sx: intermediateX2 + 50,
      sy: nodeCoordinate[curLayerIndex][i].y - (nodeLength / 2 + kernelRectLength * 2),
      tx: intermediateX2 + 2 * plusSymbolRadius + 5,
      ty: nodeCoordinate[curLayerIndex][i].y + nodeLength / 2 - plusSymbolRadius,
      dr: 50,
      hFlip: false,
      marker: 'marker-alt'
    });
  } else {
    drawArrow({
      group: group,
      sx: intermediateX2 + 35,
      sy: nodeCoordinate[curLayerIndex][i].y + nodeLength + kernelRectLength * 2,
      tx: intermediateX2 + 2 * plusSymbolRadius + 5,
      ty: nodeCoordinate[curLayerIndex][i].y + nodeLength / 2 + plusSymbolRadius,
      dr: 30,
      hFlip: true,
      marker: 'marker-alt'
    });
  }

  // Add annotation for the bias
  let biasTextY = nodeCoordinate[curLayerIndex][i].y;
  if (i === 0) {
    biasTextY += nodeLength + 3 * kernelRectLength;
  } else {
    biasTextY -= 2 * kernelRectLength + 5;
  }
  plusAnnotation.append('text')
    .attr('class', 'annotation-text')
    .attr('x', intermediateX2 + plusSymbolRadius)
    .attr('y', biasTextY)
    .style('text-anchor', 'middle')
    .style('dominant-baseline', i === 0 ? 'hanging' : 'baseline')
    .text('Bias');
}
Add an annotation for the kernel and the sliding
@param {object} arg 
{
 leftX: X value of the left border of intermedaite layer
 group: element group
 intermediateGap: the inner gap of intermediate layer
 isFirstConv: if this intermediate layer is after the first layer
 i: index of the selected node
}