Source: modules/url-sanitize.js

/** Parses URL search params and fills in missing information
 * @module
 */

import { queryItem, queryItems } from './api.js'
import { createTranslator } from '@dataforsyningen/saul'
import { configuration } from './configuration.js'
import { getYearFromCollection, getImageCenter } from '../modules/utilities.js'
import { checkBounds } from '../state/items.js'

/** Finds the collection closest to a given year */
function findClosestYear(targetYear, collections) {
  const yearList = collections.map((collection) => getYearFromCollectionID(collection.id))
  // Initialize the closest year to the first year in the list
  let closestYear = yearList[0]
  let smallestDifference = Math.abs(targetYear - closestYear)

  // Iterate through the year list to find the closest year
  for (let i = 1; i < yearList.length; i++) {
    let currentYear = yearList[i]
    let currentDifference = Math.abs(targetYear - currentYear)

    if (currentDifference < smallestDifference) {
      smallestDifference = currentDifference
      closestYear = currentYear
    }

    // When more years are equally close, use the lesser year
    if (currentDifference === smallestDifference && closestYear > currentYear) {
      closestYear = currentYear
    }
  }
  return closestYear
}

/** Returns the year number from a collection ID */
function getYearFromCollectionID(id) {
  const yearRegex = /[1-2][0-9]{3}/g
  return Number(id.match(yearRegex)[0])
}

/** 
 * Adds or modifies URL searchparams according to various edge cases 
 * @param { URL } searchparams - URL object instance with query string (ie. search parameters).
 * @param { Array } collections - List of collection objects from STAC API JSON reponse.
 */
async function sanitizeParams(searchparams, collections) {

  let params = sanitizeCoords(searchparams)

  const sortedCollections = collections.sort(function(a,b) {
    const yearA = getYearFromCollectionID(a.id)
    const yearB = getYearFromCollectionID(b.id)
    if (yearA > yearB) {
      return -1
    } else if (yearA < yearB) {
      return 1
    } else {
      return 0
    }
  })

  // Having `item` parameter overrules year and orientation (and center if coordinate is outside image)
  if (params.get('item')) {
    const item = await queryItem(params.get('item'))
    if (params.get('orientation') !== 'map') {
      params.set('orientation', item.properties.direction)
    }
    params.set('year', getYearFromCollection(item.collection))
    if (!params.get('center')) {
      params.set('center', getImageCenter(item).join(','))
    } else {
      const outsideBounds = await checkBounds(params.get('center').split(','), item)
      if (outsideBounds) {
        params.set('center', getImageCenter(item).join(','))
      }
    }
    return params
  }

  // Update `year` parameter
  if (params.get('year')) {
    params.set('year', findClosestYear(params.get('year'), collections))
  } else {
    // Use configured year or just from the latest collection
    if (configuration.DEFAULT_COLLECTION) {
      params.set('year', getYearFromCollectionID(configuration.DEFAULT_COLLECTION))
    } else {
      params.set('year', getYearFromCollectionID(sortedCollections[0].id))
    }
  }

  if (!params.get('center')) {
    params.set('center', configuration.DEFAULT_WORLD_COORDINATE.join(','))
  }

  if (!params.get('orientation')) {
    params.set('orientation', 'north')
  }

  if (params.get('orientation') !== 'map') {
    const itemData = await queryItems(params.get('center').split(','), params.get('orientation'), `skraafotos${ params.get('year') }`)
    params.set('item', itemData.features[0].id)
  }

  // Sea plane easter egg
  const center = params.get('center').split(',')
  if (center[0] === '721239' && center[1] === '6174113') {
    params.set('item', '2021_84_40_4_0037_00084342')
  }

  return params
}

/** Converts a coordinate to EPSG:25832 if it looks like a WGS84 coordinate */
function convertCoords(coords) {
  if (coords[0] < 20) {
    // If coordinate x value is below 20, we assume it is wgs84. Since longitudes across Denmark range from 6 to 16
    return createTranslator().forward(coords)
  } else {
    return coords
  }
}

/** Converts lat/lon or x/y coordinates used in URL to `center` parameter */
function sanitizeCoords(url) {

  let params = url.searchParams
  let x, y

  // If `center` param exists, return the params unchanged
  if (params.get('center')) {
    removeUnusedCoordParams(url.searchParams)
    return params
  }

  // Get param values
  const p_lat = params.get('lat')
  const p_lon = params.get('lon')
  const p_x = params.get('x')
  const p_y = params.get('y')
  const p_n = params.get('n')
  const p_e = params.get('e')

  // Check if params exist and assign values
  if (p_lat && p_lon) {
    x = Number(p_lon)
    y = Number(p_lat)
  } else if (p_x && p_y) {
    x = Number(p_x)
    y = Number(p_y)
  } else if (p_n && p_e) {
    x = Number(p_e)
    y = Number(p_n)
  } else {
    // Nothing applies. Just return params as is
    return params
  }

  params.set('center', convertCoords([x,y]))
  removeUnusedCoordParams(url.searchParams)

  return params
}

function removeUnusedCoordParams(params) {
  params.delete('lat')
  params.delete('lon')
  params.delete('x')
  params.delete('y')
  params.delete('n')
  params.delete('e')
}

function removeUnusedParams(params) {
  params.delete('width')
  params.delete('mode')
  params.delete('project')
}

export {
  sanitizeParams,
  sanitizeCoords,
  removeUnusedParams
}