
const csv = '../Locator/input.csv'
// Initial zoom
const zoom = 12

// OpenLayers - https://openlayers.org/

function OLMap (ol) {
  /* global OpenLayers */
  const mercator = OpenLayers.Projection.transforms['EPSG:4326']['EPSG:3857']

  // Layer with map
  const map = new OpenLayers.Map('map', { projection: 'EPSG:3857', controls: [] })
  const osm = new OpenLayers.Layer.OSM()

  const features = []
  const elements = []
  const lat = []
  const lon = []

  const img = 'data:image/png;base64, '

  let i = 0
  ol.forEach(element => {
    features[i] = new OpenLayers.Feature.Vector(
      mercator(new OpenLayers.Geometry.Point(element[2], element[1])),
      { id: i },
      {
        externalGraphic: img,
        graphicWidth: 48,
        graphicHeight: 48
      }
    )

    elements[i] = element[0]
    lon[i] = element[2]
    lat[i] = element[1]
    i++
  })

  // Get the center of the map
  const center = mercator({ x: (max(lon) + min(lon)) / 2, y: (max(lat) + min(lat)) / 2 })

  // Layer with listeners
  const vector = new OpenLayers.Layer.Vector(
    'Points',
    {
      eventListeners: {
        featureselected: function (evt) {
          const feature = evt.feature
          const id = feature.attributes.id
          const address = elements[id].split(', ')
          const popup = new OpenLayers.Popup(
            'popup',
            OpenLayers.LonLat.fromString(feature.geometry.toShortString()),
            null,
            '<p><b>' + address[0] + '</b><br>' +
            address[1] + '<br>' +
            '<b>Lon</b>: ' + lon[id] + '<br>' +
            '<b>Lat</b>: ' + lat[id] + '<br>',
            false
          )

          feature.popup = popup
          map.addPopup(popup)

          // Popup style
          let elem = document.getElementById('popup')
          elem.style.border = '1px solid darkgrey'
          elem.style.borderRadius = '15pt'
          elem.style.width = '160pt'
          elem.style.height = '70pt'
          elem.style.padding = '1pt 5pt'
          elem.style.margin = '20pt 0pt 0pt 0pt'
          elem.style.fontFamily = "'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif"
          elem.style.fontSize = '9pt'
          elem = document.getElementById('popup_contentDiv')
          elem.style.width = '160pt'
          elem.style.height = '70pt'
        },
        // Destroy popup
        featureunselected: function (evt) {
          const feature = evt.feature
          map.removePopup(feature.popup)
          feature.popup.destroy()
          feature.popup = null
        }
      }
    }
  )
  vector.addFeatures(features)

  // Select feature control
  const selector = new OpenLayers.Control.SelectFeature(
    vector,
    {
      toggle: true,
      clickout: true,
      autoActivate: true
    }
  )

  map.addLayers([osm, vector])

  map.addControl(new OpenLayers.Control.PanZoomBar())
  map.addControl(new OpenLayers.Control.Navigation())
  map.addControl(selector)
  map.setCenter(new OpenLayers.LonLat(center.x, center.y), zoom)
}

fetch(csv).then(
  function (r) {
    r.text().then(
      function (content) {
        const rows = CSVToArray(content, ',')
        const ol = []
        rows.forEach(row => {
          const item = []
          row.forEach(element => {
            const value = element.trim()
            item.push(value)
          })
          ol.push(item)
        })
        OLMap(ol)
      }
    )
  }
)

// Map style
const elem = document.getElementById('map')
elem.style.position = 'fixed'
elem.style.top = '0pt'
elem.style.left = '0pt'
elem.style.width = '100%'
elem.style.height = '100%'

/*
 * This will parse a delimited string into an array of arrays. The default delimiter is
 * the comma, but this can be overriden in the second argument.
 *
 * ES6 version of this function: https://www.bennadel.com/blog/1504-ask-ben-parsing-csv-strings-with-javascript-exec-regular-expression-command.htm
 *
 */

function CSVToArray (strData, strDelimiter) {
  // Check to see if the delimiter is defined. If not,
  // then default to comma.
  strDelimiter = (strDelimiter || ',')

  // Create a regular expression to parse the CSV values.
  const objPattern = new RegExp(
    (
      // Delimiters.
      '(\\' + strDelimiter + '|\\r?\\n|\\r|^)' +

      // Quoted fields.
      '(?:"([^"]*(?:""[^"]*)*)"|' +

      // Standard fields.
      '([^"\\' + strDelimiter + '\\r\\n]*))'
    ),
    'gi'
  )

  // Create an array to hold our data. Give the array
  // a default empty first row.
  const arrData = [[]]

  // Create an array to hold our individual pattern
  // matching groups.
  let arrMatches = null

  let strMatchedValue = ''

  // Keep looping over the regular expression matches
  // until we can no longer find a match.
  while ((arrMatches = objPattern.exec(strData))) {
    // Get the delimiter that was found.
    const strMatchedDelimiter = arrMatches[1]

    // Check to see if the given delimiter has a length
    // (is not the start of string) and if it matches
    // field delimiter. If id does not, then we know
    // that this delimiter is a row delimiter.
    if (
      strMatchedDelimiter.length &&
      (strMatchedDelimiter !== strDelimiter)
    ) {
      // Since we have reached a new row of data,
      // add an empty row to our data array.
      arrData.push([])
    }

    // Now that we have our delimiter out of the way,
    // let's check to see which kind of value we
    // captured (quoted or unquoted).
    if (arrMatches[2]) {
      // We found a quoted value. When we capture
      // this value, unescape any double quotes.
      strMatchedValue = arrMatches[2].replace(
        '/""/g',
        '"'
      )
    } else {
      // We found a non-quoted value.
      strMatchedValue = arrMatches[3]
    }

    // Now that we have our value string, let's add
    // it to the data array.
    arrData[arrData.length - 1].push(strMatchedValue)
  }

  // Return the parsed data.
  return (arrData)
}

function max (input) {
  if (toString.call(input) !== '[object Array]') {
    return false
  }
  return Math.max.apply(null, input)
}

function min (input) {
  if (toString.call(input) !== '[object Array]') {
    return false
  }
  return Math.min.apply(null, input)
}
