function createEnd() {

  //find X and Y

  var X = stage.width() - stage.width() / 100 * 5;
  if (endHeight === 50) {
    var Y = stage.height() / 2 - endHeight;
  } else {
    var Y = stage.height() / 2 - endHeight;
  }


  var endShape = new Konva.Rect({
    x: X - 25,
    y: Y - 25,
    fill: colorEnd,
    width: 50,
    height: endHeight,
    stroke: 'black',
    strokeWidth: 4,
    id: "end",
  });
  end = {
    name: "end",
    x: X,
    y: Y,
    type: "end",
    position: 1,
    let: 1,
  }
  end.x = end.x - endShape.width() / 2;
  layer.add(endShape);
}

function createCircle(x, y, logiqueName) {
  var circle = new Konva.Circle({
    id: "circle" + circles.length,
    x: x,
    y: y,
    radius: 10,
    fill: 'black',
    stroke: 'black',
    strokeWidth: 4,
  });
  circles.push("circle" + idLine);
  layer.add(circle);
}

function createSwitch(id, x, y) {
  var switche = {
    id: id,
    x: x,
    y: y,
    id3: [],
  };
  switchsInfo.push(switche);
  switchsInfoCopy.push(switche);
  switchs.push(id);
  var num = lineCount.length;
  lineCount.push(1);
  var rect1 = new Konva.Rect({
    x: x,
    y: y,
    width: SwitchWidth,
    height: SwitchHeight,
    stroke: colorSwitchBorder,
    fill: colorSwitchInnactiveBackground,
    strokeWidth: 4,
    id: id,
    id3: null,
  });
  layer.add(rect1);
}

function createLine(points, id, end) {
  let startX = points[0],
    startY = points[1],
    endX = points[2],
    endY = points[3];
  var newPoints;
  if (end != undefined && end != null && end === true) {
    let distance20 = (endX - startX) / 100 * 5;
    let distance80 = (endX - startX) / 100 * 90;
    newPoints = [startX, startY, startX + distance80, startY, endX - distance20, endY, endX, endY];
  } else if (end != undefined && end != null && end === false) {
    let distance20 = (endX - startX) / 100 * 10;
    let distance80 = (endX - startX) / 100 * 80;
    newPoints = [startX, startY, startX + distance80, startY, endX - distance20, endY, endX, endY];
  } else {
    let distance20 = (endX - startX) / 100 * pourcentageBreak;
    newPoints = [startX, startY, startX + distance20, startY, endX - distance20, endY, endX, endY];
  }

  var change = [
    [],
    [],
    []
  ];
  for (let j = 0; j < 3; j++) {
    var maxX = newPoints[2 + (2 * j)] - newPoints[0 + (2 * j)],
      resteX = newPoints[0 + (2 * j)],
      maxY = newPoints[1 + (2 * j)] - newPoints[3 + (2 * j)],
      isGoingUp = function () {
        if (newPoints[1 + (2 * j)] < newPoints[3 + (2 * j)])
          return true;
        else return false
      }
    resteY = newPoints[3 + (2 * j)];
    iscollapsing = false;

    for (let i = 0; i < 100; i++) {
      iscollapsing = false;
      var x = (maxX / 100 * i) + resteX;
      if (isGoingUp)
        var y = (maxY - (maxY / 100 * i)) + resteY;
      else var y = (maxY / 100 * i) + resteY;
      logiques.forEach(function (logique) {
        if (x > logique.x && x < logique.x + imageWidth && y > logique.y && y < logique.y + imageHeight) iscollapsing = true;
        if (iscollapsing) {
          change[j].push([x, y]);
        }
      });
    }
    if (change[j].length !== 0) {
      while (change[j].length !== 0) {

        newPoints[1 + (2 * (j + 1))] = newPoints[1 + (2 * (j + 1))] + 7;
        var maxX = newPoints[2 + (2 * j)] - newPoints[0 + (2 * j)],
          resteX = newPoints[0 + (2 * j)],
          maxY = newPoints[1 + (2 * j)] - newPoints[3 + (2 * j)],
          isGoingUp = function () {
            if (newPoints[1 + (2 * j)] < newPoints[3 + (2 * j)])
              return true;
            else return false
          }
        resteY = newPoints[3 + (2 * j)];
        iscollapsing = false;
        change[j] = [];
        for (let i = 0; i < 100; i++) {
          iscollapsing = false;
          var x = (maxX / 100 * i) + resteX;
          if (isGoingUp)
            var y = (maxY - (maxY / 100 * i)) + resteY;
          else var y = (maxY / 100 * i) + resteY;
          logiques.forEach(function (logique) {
            if (x > logique.x && x < logique.x + imageWidth && y > logique.y && y < logique.y + imageHeight) iscollapsing = true;
            if (iscollapsing) {
              change[j].push([x, y]);
            }
          });
        }
      }
      /*var changePoints = [],
        YAdd = 4,
        oldX = newPoints[0 + (2 * j)],
        oldY = newPoints[1 + (2 * j)],
        debBaseX = change[j][0][0],
        debBaseY = change[j][0][1] + YAdd,
        finBaseX = change[j][change[j].length - 1][0],
        finBaseY = change[j][change[j].length - 1][1] + YAdd,
        newStartX = debBaseX - ((finBaseX - debBaseX)),
        newStartY = debBaseY + YAdd,
        newStartX2 = debBaseX,
        newStartY2 = debBaseY + (imageHeight) + YAdd,
        newStartX3 = finBaseX,
        newStartY3 = finBaseY + (imageHeight) + YAdd,
        newStartX4 = finBaseX + ((finBaseX - debBaseX)),
        newStartY4 = finBaseY + YAdd,
        indexStart = newPoints.indexOf(newPoints[0 + (2 * j)]);
      console.log(indexStart);
      changePoints.push(newStartY4, newStartX4, newStartY3, newStartX3, newStartY2, newStartX2, newStartY, newStartX, oldY, oldX);
      //on supprime les anciens points :
      newPoints.splice(indexStart, 4);
      console.log(newPoints);
      for (let k = 0; k < changePoints.length; k++)
        newPoints.splice(indexStart, 0, changePoints[k]);
      console.log(newPoints);*/
    }
  }

  let line = new Konva.Line({
    points: newPoints,
    stroke: colorLineInnactive,
    strokeWidth: lineStroke,
    id: id,
    tension: tension,
  });
  var lineObj = {
    id: id,
    state: false,
  };
  lines.push(lineObj);
  layer.add(line);
  if (iscollapsing) line.stroke("red");
}


function createLink(entre, sortie, infoId) {
  //entre est une porte logique
  lineId = lineCount.length;
  lineCount.push(1);
  switch (whatIsElement(entre)) {
    case "switch":
      switch (whatIsElement(sortie)) {
        case "logique":
          switch (giveLineId(sortie.name, entre)) {
            case "id1":
              let switchMidX = entre.getX() + entre.getWidth();
              let switchMidY = entre.getY() + entre.getHeight() / 2;

              let logiqueMidX = sortie.x;
              if (sortie.type === "inv") {
                var logiqueMidY = sortie.y + (imageHeight / 2);
              } else {
                var logiqueMidY = sortie.y + (imageHeight / 3);
              }
              createLine([switchMidX, switchMidY, logiqueMidX, logiqueMidY], "line" + lineId, false);
              setLine(sortie, "id1", "line" + lineId);

              let truc = entre.x;
              getSwitchById(entre.id()).id3.push("line" + lineId);
              break;
            case "id2":

              createLine([entre.getX() + entre.getWidth(), entre.getY() + entre.getHeight() / 2, sortie.x, sortie.y + (imageHeight / 3) * 2], "line" + lineId, false);
              setLine(sortie, "id2", "line" + lineId);
              getSwitchById(entre.id()).id3.push("line" + lineId);

              break;
          }
      }
      break;
    case "logique":
      switch (whatIsElement(sortie)) {
        case "logique":
          if (infoId === undefined || infoId === null) {
            console.log('bug')
          }
          else if (infoId === 0) {
            switch (giveLineId(sortie.name, entre)) {
              case "id1":
                let switchMidX = entre.x + imageWidth;
                let switchMidY = entre.y + imageHeight / 2;

                let logiqueMidX = sortie.x;
                if (sortie.type === "inv") {
                  var logiqueMidY = sortie.y + (imageHeight / 2);
                } else {
                  var logiqueMidY = sortie.y + (imageHeight / 3);
                }
                createLine([switchMidX, switchMidY, logiqueMidX, logiqueMidY], "line" + lineId);
                setLine(sortie, "id1", "line" + lineId);
                setLine(entre, "id3", "line" + lineId);
                break;
              case "id2":
                createLine([entre.x + imageWidth, entre.y + imageHeight / 2, sortie.x, sortie.y + (imageHeight / 3) * 2], "line" + lineId);
                setLine(sortie, "id2", "line" + lineId);
                setLine(entre, "id3", "line" + lineId);
                break;
            }

          } else {
            if (infoId === "id1") {
              let switchMidX = entre.x + imageWidth;
              let switchMidY = entre.y + imageHeight / 2;

              let logiqueMidX = sortie.x;
              if (sortie.type === "inv") {
                var logiqueMidY = sortie.y + (imageHeight / 2);
              } else {
                var logiqueMidY = sortie.y + (imageHeight / 3);
              }
              createLine([switchMidX, switchMidY, logiqueMidX, logiqueMidY], "line" + lineId);
              setLine(sortie, "id1", "line" + lineId);
              setLine(entre, "id3", "line" + lineId);
            } else {
              createLine([entre.x + imageWidth, entre.y + imageHeight / 2, sortie.x, sortie.y + (imageHeight / 3) * 2], "line" + lineId);
              setLine(sortie, "id2", "line" + lineId);
              setLine(entre, "id3", "line" + lineId);
            }
          }
          break;
        default:
          endLines.push(lineId);
          if (end.position === 1) createLine([entre.x + imageWidth, entre.y + imageHeight / 2, sortie.x, (stage.findOne("#end").getY() + endHeight / 2)], "line" + lineId, true);
          else createLine([entre.x + imageWidth, entre.y + imageHeight / 2, sortie.x, (stage.findOne("#end").getY() + endHeight / (end.position + 1) * end.let)], "line" + lineId, true);

          setLine(entre, "id3", "line" + lineId);
          end.let--;
          break;
      }
      break;
    default:
      console.log("error");
      break;
  }
}

function createLogique(x, y, id, type) {
  var imageObj = new Image();
  imageObj.onload = function () {
    var et = new Konva.Image({
      x: x,
      y: y,
      image: imageObj,
      width: imageWidth,
      height: imageHeight,
      id: id,
    });
    if (imageRotation != 0) {
      et.rotation(imageRotation);
      et.x(et.getX() + imageHeight);
    }
    layer.add(et);
    layer.batchDraw();
  };
  switch (type) {
    case "et":
      imageObj.src = pathImg + imageLogiqueEt;
      break;
    case "ou":
      imageObj.src = pathImg + imageLogiqueOu;
      break;
    case "etnon":
      imageObj.src = pathImg + imageLogiqueEtNon;
      break;
    case "inv":
      imageObj.src = pathImg + imageLogiqueInv;
      break;
    case "nonou":
      imageObj.src = pathImg + imageLogiqueNonOu;
      break;
  }

  imageObj.id = id;



  var logique = {
    name: id,
    x: x,
    y: y,
    type: type,
    id1: null,
    id2: null,
    id3: [],
  }
  logiques.push(logique);
}

function switchCreator(number) {
  numberOfSwitch = number;
  let split = number + 1;
  let space = (stage.height() - stage.height() / 100 * 25) / split;
  for (let i = 1; i < number + 1; i++) {
    createSwitch("s" + i, 20, (i) * space);
  }
}

function insertLogiqueColonne(nomLogique, TypeLogique, colonne) {
  var X = stage.width() / (colonneTot + 1) * (colonne + 1);
  //calcul position Y
  if (numberPerColonne[colonne] == 1) {
    var Y = stage.height() / 3;
  } else {
    let numberAlreadyAdded = liveColonneNumber[colonne].length + 1;
    let split = (stage.height() - stage.height() / 100 * 25) / (numberPerColonne[colonne] + 1);
    var Y = split * numberAlreadyAdded;
  }
  createLogique(X, Y, nomLogique, TypeLogique);
  liveColonneNumber[colonne].push(1);
}

function createLinkSwitch() {
  var logique = null;
  var distance = stage.width();
  //Trouver la porte logique la plus proche des switchs
  logiques.forEach(function (element) {
    if (element.type != "inv") {
      if (element.id1 == null || element.id2 == null) {
        if (element.x < distance) {
          logique = element;
          distance = element.x;
        }
      }
    } else {
      if (element.id1 == null) {
        if (element.x < distance) {
          logique = element;
          distance = element.x;
        }
      }
    }
  });
  var distanceSwitch = stage.height();
  var switchs = null;
  if (switchsInfo.length > 0) {
    switchsInfo.forEach(function (element) {
      if (Math.abs(logique.y - element.y) < distanceSwitch) {
        distanceSwitch = Math.abs(logique.y - element.y);
        switchs = element;
      }
    });
  } else {
    switchsInfoCopy.forEach(function (element) {
      if (stage.findOne("#" + element.id).id3.length === 0) {
        if (Math.abs(logique.y - element.y) < distanceSwitch) {
          distanceSwitch = Math.abs(logique.y - element.y);
          switchs = element;
        }
      }
    });
  }

  switchsInfo.splice(switchsInfo.indexOf(switchs), 1);

  createLink(stage.findOne("#" + switchs.id), findLogique(logique.name));
}

function getNumberOfSwitchEmpty() {
  let number = 0;
  switchsInfoCopy.forEach(function (element) {
    if (stage.findOne("#" + element.id).id3.length === 0)
      number++;
  });
  return number;
}

function createAllLinkSwitch() {
  for (let i = 0; i < numberOfSwitch; i++) {
    createLinkSwitch();
  }
  /*while (getNumberOfSwitchEmpty() > 0) {
    createLinkSwitch();
  }*/
}

function createLinkAuto(logiqueId) {
  var logique = findLogique(logiqueId);
  var ligneSupCoor = null;
  var stop = false;
  //on cherche la ligne supérieur
  logiques.forEach(function (element) {
    if (!stop) {
      if (logique.x < element.x) {
        stop = true;
        ligneSupCoor = element.x;
      }
    }
  });
  if (ligneSupCoor != null) {
    //on stock les portes logiques de la lignes supérieur (si il reste de la place dans leur entrees)
    var ligneSup = [];
    logiques.forEach(function (element) {

      if (element.x == ligneSupCoor) {
        if (checkLogiqueLines(element.name, "id1") == false || checkLogiqueLines(element.name, "id2") == false) {
          ligneSup.push(element);
        }
      }
    });

    var distance = findLogique(logiqueId).y;
    var logiqueMatch = null;
    ligneSup.forEach(function (element) {
      if (Math.abs(findLogique(logiqueId).y - element.y) < distance) {
        distance = Math.abs(findLogique(logiqueId).y - element.y);
        logiqueMatch = element;
      }
    });
    createLink(findLogique(logiqueId), logiqueMatch);
    if (double && logiqueMatch.type != "inv") {
      var distance2 = logique.y * 1500;
      var logique2 = null;
      ligneSup.splice(ligneSup.indexOf(logiqueMatch), 1);
      ligneSup.forEach(function (element) {
        if (Math.abs(logique.y - element.y) < distance2 && element.type != "inv") {
          distance2 = Math.abs(findLogique(logiqueId).y - element.y);
          logique2 = element;
        }
      });
      if (logique2 != null) {
        createLink(findLogique(logiqueId), logique2);
        double = false;
      }
    }
  }
}

function createStage(container) {
  height = document.querySelector("#" + container).offsetHeight;
  width = document.querySelector("#" + container).offsetWidth;
  if (window.innerWidth <= 900) {
    if (!mobile) {
      mobile = true;
      stage = new Konva.Stage({
        container: container,
        width: height,
        height: width,
        rotation: 90,
        x: height,
      });
    }
    stage = new Konva.Stage({
      container: container,
      width: height,
      height: width,
      rotation: 90,
      x: height,
    });

  } else {
    if (mobile) {
      mobile = false;
    } else {
      stage = new Konva.Stage({
        container: container,
        width: width,
        height: height,
      });
    }
  }
  stage.draw();
}