const options = {
  legend: {
    position: "nw",
    show: true,
    noColumns: 2,
  },
  zoom: {
    interactive: true
  },
  pan: {
    interactive: true,
    cursor: "move",
    frameRate: 60
  },
  series: {
    lines: {
      show: true,
      lineWidth: 2
    }
  },
  xaxis: {
    tickDecimals: 2,
    tickSize: 0.01
  },
  yaxis: {
    tickDecimals: 2,
    tickSize: 0.01
  }
}

window.onload = function() {
  const fileSelector = document.getElementById('file-selector')

  fileSelector.addEventListener('change', (event) => {
    const fileList = event.target.files;
    console.log(fileList);
    importFiles(fileList)
  })

  const dropArea = document.getElementsByClassName('content')[0];

  dropArea.addEventListener('dragover', (event) => {
    event.stopPropagation();
    event.preventDefault();
    // Style the drag-and-drop as a "copy file" operation.
    event.dataTransfer.dropEffect = 'copy';
  });

  dropArea.addEventListener('drop', (event) => {
    event.stopPropagation();
    event.preventDefault();
    const fileList = event.dataTransfer.files;
    console.log(fileList);
    importFiles(fileList)
  });
}
function importFiles(fileList) {
  d = []
  plot = $.plot("#placeholder", d, options);
  for (const file of fileList) {

    if(file.name?.toLowerCase().endsWith(".txt"))
      readTxtFile(file)
    else if (file.name?.toLowerCase().endsWith(".nmea"))
      parseNmeaFile(file)
  }
}

function readTxtFile(file) {
  const reader = new FileReader()
  reader.addEventListener('load', (event) => {
    const lines = event.target.result.split('\n')
    let result = []
    for(const line of lines) {
      const fields = line.split(',')
      if(fields.length != 8)
        continue
      
      result.push({
        timestamp: fields[0],
        lat: parseFloat(fields[1]),
        lng: parseFloat(fields[2]),
        alt: parseFloat(fields[3]),
        hdop: parseInt(fields[4]),
        speed: parseInt(fields[5])
      })
    }
    process(file.name, result)
  });
  reader.readAsText(file)
}

function parseNmeaFile(file) {
  const reader = new FileReader()

  reader.addEventListener('load', (event) => {
    const lines = event.target.result.split('\n')
    let result = []
    let ggaObj, oldTime;
  
    for(const line of lines) {
      const obj = GPS.Parse(line);
      if (obj.type == "RMC") {
        if(ggaObj.time != oldTime) {
          oldTime = ggaObj.time
          result.push({
            timestamp: ggaObj.time,
            lat: ggaObj.lat,
            lng: ggaObj.lon,
            alt: ggaObj.alt,
            hdop: ggaObj.hdop,
            speed: obj.speed
          })
        }
        ggaObj = null
      } else if(ggaObj) {
        if(ggaObj.time != oldTime) {
          oldTime = ggaObj.time
          result.push({
            timestamp: ggaObj.time,
            lat: ggaObj.lat,
            lng: ggaObj.lon,
            alt: ggaObj.alt,
            hdop: ggaObj.hdop,
            speed: null
          })
        }
        ggaObj = null
      } 
      if(obj.type == "GGA") {
        ggaObj = obj;
      }
    }
    process(file.name, result)
  });
  reader.readAsText(file)
}

function process(name, markers) {
  d.push({
    label: `${name} ${markers.length}`,
    data: markers.map(m => [m.lat, m.lng])
  })
  markers = RamerDouglasPeucker2d(markers, 0.00001) //.0001 = 7m
  d.push({
    label: `RamerDouglasPeucker2d ${markers.length}`,
    data: markers.map(m => [m.lat, m.lng])
  })

  plot.setData(d);
  plot.setupGrid(); //only necessary if your new data will change the axes or grid
  plot.draw();
}

function perpendicularDistance2d(ptX, ptY, l1x, l1y, l2x, l2y) {
  if (l2x == l1x)
  {
    //vertical lines - treat this case specially to avoid dividing
    //by zero
    return Math.abs(ptX - l2x);
  }
  else
  {
    const slope = ((l2y-l1y) / (l2x-l1x));
    const passThroughY = (0-l1x)*slope + l1y;
    return (Math.abs((slope * ptX) - ptY + passThroughY)) /
              (Math.sqrt(slope*slope + 1));
  }
}
function RamerDouglasPeucker2d(pointList, epsilon) {
  if (pointList.length < 2)
  {
    return pointList;
  }
  // Find the point with the maximum distance
  let dmax = 0;
  let index = 0;
  let totalPoints = pointList.length;
  for (let i = 1; i < (totalPoints - 1); i++)
  {
    let d = perpendicularDistance2d(
          pointList[i].lat, pointList[i].lng,
          pointList[0].lat, pointList[0].lng,
          pointList[totalPoints-1].lat,
          pointList[totalPoints-1].lng);
    if (d > dmax)
    {
      index = i;
      dmax = d;
    }
  }
  
  // If max distance is greater than epsilon, recursively simplify
  if (dmax >= epsilon)
  {
    // Recursive call on each 'half' of the polyline
    const recResults1 = RamerDouglasPeucker2d(pointList.slice(0, index + 1), epsilon);
    const recResults2 = RamerDouglasPeucker2d(pointList.slice(index), epsilon);
    // Build the result list
    return recResults1.slice(0, recResults1.length - 1).concat(recResults2);
  }
  else
  {
    return [pointList[0], pointList[totalPoints-1]];
  }
}