text: import { API_URL, ID_EDITOR_URL, POTLATCH2_EDITOR_URL } from '../config';
  import { getCentroidAndZoomFromSelectedTasks, getSelectedTasksBBox } from './tasksGeometry';
  
  export function openEditor(
    editor,
    project,
    tasks,
    selectedTasks,
    windowSize,
    windowObjectReference,
  ) {
    if (editor === 'JOSM') {
      sendJosmCommands(project, tasks, selectedTasks, windowSize);
      return '?editor=JOSM';
    }
    const { center, zoom } = getCentroidAndZoomFromSelectedTasks(tasks, selectedTasks, windowSize);
    if (['ID', 'RAPID'].includes(editor)) {
      return getIdUrl(project, center, zoom, selectedTasks, ('?editor=' + editor));
    }
    if (windowObjectReference == null || windowObjectReference.closed) {
      windowObjectReference = window.open('', `iD-${project}-${selectedTasks}`);
    }
    if (editor === 'POTLATCH_2') {
      windowObjectReference.location.href = getPotlatch2Url(center, zoom);
      return '?editor=POTLATCH_2';
    }
    if (editor === 'FIELD_PAPERS') {
      windowObjectReference.location.href = getFieldPapersUrl(center, zoom);
      return '?editor=FIELD_PAPERS';
    }
    if (editor === 'CUSTOM') {
      const customUrl = project.customEditor.url;
      windowObjectReference.location.href = getIdUrl(project, center, zoom, selectedTasks, customUrl);
      return '?editor=CUSTOM';
    }
  }
  
  export function formatImageryUrl(imageryURL) {
    // url is supposed to look like tms[22]:http://hiu...
    if (imageryURL) {
      return imageryURL.substring(imageryURL.indexOf('http')).replace('zoom', 'z');
    }
  }
  
  export function getTaskGpxUrl(projectId, selectedTasks) {
    return new URL(
      `projects/${projectId}/tasks/queries/gpx/?tasks=${selectedTasks.join(',')}`,
      API_URL,
    ).href;
  }
  
  export function getTaskXmlUrl(projectId, selectedTasks) {
    return new URL(
      `projects/${projectId}/tasks/queries/xml/?tasks=${selectedTasks.join(',')}`,
      API_URL,
    );
  }
  
  export function getFieldPapersUrl(centroid, zoomLevel) {
    return `http://fieldpapers.org/compose#${[
      zoomLevel,
      roundToDecimals(centroid[1], 5),
      roundToDecimals(centroid[0], 5),
    ].join('/')}`;
  }
  
  export function getPotlatch2Url(centroid, zoomLevel) {
    return `${POTLATCH2_EDITOR_URL}#map=${[
      zoomLevel,
      roundToDecimals(centroid[1], 5),
      roundToDecimals(centroid[0], 5),
    ].join('/')}`;
  }
  
  export function getIdUrl(project, centroid, zoomLevel, selectedTasks, customUrl) {
    const base = customUrl ? formatCustomUrl(customUrl) : `${ID_EDITOR_URL}`;
    let url = base + '#map=' + [zoomLevel, centroid[1], centroid[0]].join('/');
    // the other URL params are only needed by external iD editors
    if (!['?editor=ID','?editor=RAPID'].includes(customUrl)) {
      if (project.changesetComment) {
        url += '&comment=' + encodeURIComponent(project.changesetComment);
      }
      if (project.imagery) {
        if (project.imagery.includes('http')) {
          url += '&background=custom:' + encodeURIComponent(formatImageryUrl(project.imagery));
        } else {
          url += '&background=' + encodeURIComponent(formatImageryUrl(project.imagery));
        }
      }
      // add GPX
      if (project.projectId && selectedTasks) {
        url += '&gpx=' + encodeURIComponent(getTaskGpxUrl(project.projectId, selectedTasks));
      }
      if (project.idPresets) {
        url += '&presets=' + encodeURIComponent(project.idPresets.join(','));
      }
    }
    return url;
  }
  
  export const sendJosmCommands = async (project, tasks, selectedTasks, windowSize, taskBbox) => {
    await loadTasksBoundaries(project, selectedTasks);
    await loadImageryonJosm(project);
    await selectedTasks.map(
      async (task, n) =>
        await loadOsmDataToTasks(
          project,
          taskBbox ? taskBbox : getSelectedTasksBBox(tasks, [task]),
          n === 0 ? true : false,
        ),
    );
    return true;
  };
  
  // creates a new layer on JOSM and then add the tasks boundaries
  function loadTasksBoundaries(project, selectedTasks) {
    const layerName = `Boundary for task${selectedTasks.length > 1 ? 's:' : ':'} ${selectedTasks.join(
      ',',
    )} of TM Project #${project.projectId} - Do not edit or upload`;
    const emptyTaskLayerParams = {
      new_layer: true,
      layer_name: layerName,
      data:
        '<?xml version="1.0" encoding="utf8"?><osm generator="JOSM" upload="never" version="0.6"></osm>',
    };
    const tmTaskLayerParams = {
      new_layer: false,
      url: getTaskXmlUrl(project.projectId, selectedTasks).href,
    };
  
    return callJosmRemoteControl(formatJosmUrl('load_data', emptyTaskLayerParams)).then((result) =>
      callJosmRemoteControl(formatJosmUrl('import', tmTaskLayerParams)),
    );
  }
  
  export function getImageryInfo(url) {
    const type = url.toLowerCase().substr(0, 3) === 'wms' ? 'wms' : 'tms';
    const zoom = url.substr(url.indexOf('[') + 1, url.indexOf(']') - url.indexOf('[') - 1);
    const [minZoom, maxZoom] = zoom.length
      ? zoom.indexOf(':') !== -1
        ? zoom.split(':')
        : [null, zoom]
      : [null, null];
    return [
      type,
      minZoom !== '' && minZoom !== null ? Number(minZoom) : null,
      maxZoom !== '' && maxZoom !== null ? Number(maxZoom) : null,
    ];
  }
  
  function loadImageryonJosm(project) {
    if (project.imagery) {
      if (project.imagery.includes('http')) {
        const [type, minZoom, maxZoom] = getImageryInfo(project.imagery);
        const imageryParams = {
          title: project.imagery,
          type: type,
        };
        if (minZoom) imageryParams.min_zoom = minZoom;
        if (maxZoom) imageryParams.max_zoom = maxZoom;
        imageryParams.url = project.imagery.substr(project.imagery.indexOf('http'));
  
        return callJosmRemoteControl(formatJosmUrl('imagery', imageryParams));
      } else {
        return callJosmRemoteControl(formatJosmUrl('imagery', { id: project.imagery }));
      }
    }
  }
  
  function loadOsmDataToTasks(project, bbox, newLayer) {
    const emptyOSMLayerParams = {
      new_layer: newLayer,
      layer_name: 'OSM Data',
      data: '<?xml version="1.0" encoding="utf8"?><osm generator="JOSM" version="0.6"></osm>',
    };
    const loadAndZoomParams = {
      left: bbox[0],
      bottom: bbox[1],
      right: bbox[2],
      top: bbox[3],
      changeset_comment: project.changesetComment,
      changeset_source: project.imagery ? project.imagery : '',
      new_layer: false,
    };
  
    return callJosmRemoteControl(formatJosmUrl('load_data', emptyOSMLayerParams)).then((result) => {
      return callJosmRemoteControl(formatJosmUrl('load_and_zoom', loadAndZoomParams));
    });
  }
  
  export function formatJosmUrl(endpoint, params) {
    return new URL(formatUrlParams(params), `http://127.0.0.1:8111/${endpoint}`);
  }
  
  export function formatCustomUrl(url) {
    return url.includes('?') ? url : `${url}?`;
  }
  
  function roundToDecimals(input, decimals) {
    const p = Math.pow(10, decimals);
    return Math.round(input * p) / p;
  }
  
  export function formatUrlParams(params) {
    const urlParams = Object.keys(params)
      .map((key) => `${key}=${encodeURIComponent(params[key])}`)
      .join('&');
    return `?${urlParams}`;
  }
  
  let safariWindowReference = null;
  const callJosmRemoteControl = function (uri) {
    // Safari won't send AJAX commands to the default (insecure) JOSM port when
    // on a secure site, and the secure JOSM port uses a self-signed certificate
    // that requires the user to jump through a bunch of hoops to trust before
    // communication can proceed. So for Safari only, fall back to sending JOSM
    // requests via the opening of a separate window instead of AJAX.
    // Source: https://github.com/osmlab/maproulette3
    if (window.safari) {
      return new Promise((resolve, reject) => {
        if (safariWindowReference && !safariWindowReference.closed) {
          safariWindowReference.close();
        }
  
        safariWindowReference = window.open(uri);
  
        // Close the window after 1 second and resolve the promise
        setTimeout(() => {
          if (safariWindowReference && !safariWindowReference.closed) {
            safariWindowReference.close();
          }
          resolve(true);
        }, 1000);
      });
    }
  
    return fetch(uri)
      .then((response) => response.status === 200)
      .catch((error) => {
        console.log(error);
        return false;
      });
  };
  