import LCal from "../../../calendar/lcal";
import cfg from "../../timelineconfig";
import Helper from "../../../helper/helper";
import roundedRect from "../roundrectpainter";

const paintChart = (ctx, model, task, labelHeight, alignedStart, alignedEnd, resStartY, height, dataset, timeForXPosProvider) => {
  const adaptedHeight = height - 2 * cfg.getTaskBarInset(model, task) - 2 * cfg.CHART_INSET - labelHeight;

  if (adaptedHeight > 10) {
    ctx.save();

    try {
      ctx.rect(alignedStart, resStartY, alignedEnd - alignedStart, height);
      ctx.clip();

      if (dataset.charts && dataset.charts.length > 0) {
        for (let chart of dataset.charts) {
          let isFirst = true;
          let minValue = Number.MAX_VALUE;
          let maxValue = Number.MIN_VALUE; //Kleinste und größte Werte bestimmen

          for (let ds of chart.dataset) {
            let val = ds.value * 1;

            if (val < minValue) {
              minValue = val;
            }

            if (val > maxValue) {
              maxValue = val;
            }
          }

          const valueRange = maxValue - minValue;
          const factor = adaptedHeight / valueRange; //In welche 10er Potenzen lässt sich der valueRange aufteilen?

          let tickspacing = Math.pow(10, ("" + Math.round(valueRange / 10)).length - 1);
          let tickStart = Math.floor(minValue / tickspacing) * tickspacing; //Tickspacing*factor muss mindestens etwas mehr sein als die Schrifthöhe

          for (let n = 0; n < 100; n++) {
            if (tickspacing * factor >= 12) {
              break;
            }

            tickspacing += tickspacing;
          }

          ctx.setLineDash([1, 3]);
          ctx.strokeStyle = "#777";
          ctx.font = cfg.resSubFont;
          ctx.fillStyle = "#000";
          ctx.beginPath();

          while (tickStart <= maxValue) {
            let y = resStartY + cfg.CHART_INSET + adaptedHeight - (tickStart - minValue) * factor;
            ctx.fillText(tickStart, alignedStart + cfg.CHART_INSET, y);
            ctx.moveTo(alignedStart + cfg.CHART_INSET + 50, y);
            ctx.lineTo(alignedEnd - cfg.CHART_INSET, y);
            tickStart += tickspacing;
          }

          ctx.stroke();
          ctx.setLineDash([]);
          ctx.beginPath();
          ctx.strokeStyle = chart.color;

          for (let ds of chart.dataset) {
            const da = ds.date.split(' ');
            const lcal = new LCal().initYMDHM(da[2] * 1, da[1] * 1, da[0] * 1, da[3] * 1, da[4] * 1);
            const xPos = timeForXPosProvider.getXPosForTime(lcal.getJulianMinutes());

            if (xPos > alignedStart + cfg.CHART_INSET + 50) {
              if (isFirst) {
                ctx.moveTo(xPos, resStartY + cfg.CHART_INSET + adaptedHeight - factor * (ds.value - minValue));
                isFirst = false;
              } else {
                ctx.lineTo(xPos, resStartY + cfg.CHART_INSET + adaptedHeight - factor * (ds.value - minValue));
              }
            }
          }

          ctx.stroke();
        }
      }
    } catch (e) {
      console.log(e);
    }

    ctx.restore();
  }
};

const paintChartMouseOverLabel = (ctx, labelHeight, model, task, mouseLCal, resStartY, timeForXPosProvider, fontProvider) => {
  if (mouseLCal) {
    const adaptedHeight = model.getHeight(task.getID()) - 2 * cfg.getTaskBarInset(model, task) - 2 * cfg.CHART_INSET - labelHeight;

    if (adaptedHeight > 10) {
      let dataset = JSON.parse(task.dataset); //TODO: Cache

      for (let chart of dataset.charts) {
        let minValue = Number.MAX_VALUE;
        let maxValue = Number.MIN_VALUE; //Kleinste und größte Werte bestimmen

        for (let ds of chart.dataset) {
          let val = ds.value * 1;

          if (val < minValue) {
            minValue = val;
          }

          if (val > maxValue) {
            maxValue = val;
          }
        }

        const valueRange = maxValue - minValue;
        const factor = adaptedHeight / valueRange;
        ctx.save();
        let previousLCal;
        let previousYValue;

        for (let ds of chart.dataset) {
          const da = ds.date.split(' ');
          const lcal = new LCal().initYMDHM(da[2] * 1, da[1] * 1, da[0] * 1, da[3] * 1, da[4] * 1);

          if (previousLCal && !mouseLCal.before(previousLCal) && !mouseLCal.after(lcal)) {
            const successorX = timeForXPosProvider.getXPosForTime(lcal.getJulianMinutes());
            const previousX = timeForXPosProvider.getXPosForTime(previousLCal.getJulianMinutes());
            const deltaX = successorX - previousX;
            const deltaY = ds.value - previousYValue;
            const x = timeForXPosProvider.getXPosForTime(mouseLCal.getJulianMinutes());
            const valy = previousYValue + deltaY * (x - previousX) / deltaX;
            const y = resStartY + cfg.CHART_INSET + adaptedHeight - factor * (valy - minValue);
            ctx.fillStyle = chart.color;
            ctx.lineWidth = 4;
            ctx.strokeStyle = "#FF0000";
            ctx.beginPath();
            ctx.arc(x, y, 10, 0, Math.PI * 2);
            ctx.stroke();
            ctx.font = fontProvider.getTimelineBarHeaderFont();
            const labelStr = Math.round(valy * 100) / 100 + " " + chart.unit;
            const width = Helper.textWidthFromCache(labelStr, fontProvider.getTimelineBarHeaderFontSize(), ctx) + 10;
            ctx.beginPath();
            roundedRect(ctx, x + 20, y - fontProvider.getTimelineBarHeaderFontSize(), width, fontProvider.getTimelineBarHeaderFontSize() + 10, 5, 5, true);
            ctx.fillStyle = "#666";
            ctx.strokeStyle = "#AAA";
            ctx.lineWidth = 1;
            ctx.fill();
            ctx.stroke();
            ctx.fillStyle = "#FFF";
            ctx.fillText(labelStr, x + 25, y + 3);
          }

          previousYValue = ds.value * 1;
          previousLCal = lcal;
        }

        ctx.restore();
      }
    }
  }
};

export { paintChart, paintChartMouseOverLabel };