<?php

use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\View;

/**
 * @var array<mixed> $data
 * @var array<mixed> $provider
 */
?>

<div class="py-4">
    <div class="row gchart osm-wrapper">
        <div id="osm-map" class="col-sm-9 wt-ajax-load osm-user-map" dir="ltr"></div>
        <ul class="col-sm-3 osm-sidebar wt-page-options-value list-unstyled px-md-1"></ul>
    </div>
</div>

<?php View::push('styles') ?>
<style>
    .osm-wrapper, .osm-user-map {
        height: 70vh
    }

    .osm-sidebar {
        height: 100%;
        overflow-y: auto;
        font-size: small;
    }

</style>
<?php View::endpush() ?>

<?php View::push('javascript') ?>
<script>
'use strict';

window.WT_OSM = (function () {
  const minZoom = 2;

  let map      = null;
  let zoom     = null;
  let sidebar  = $('.osm-sidebar');
  let provider = <?= json_encode($provider) ?>;

// Map components
  let markers = L.markerClusterGroup({
    showCoverageOnHover: false,
  });

  let resetControl = L.Control.extend({
    options: {
      position: 'topleft',
    },
    onAdd:   function (map) {
      let container     = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom');
      container.onclick = function () {
        if (zoom) {
          map.flyTo(markers.getBounds().getCenter(), zoom);
        } else {
          map.flyToBounds(markers.getBounds().pad(0.2));
        }
        sidebar.scrollTo(sidebar.children(':first'));

        return false;
      };
      let reset         = <?= json_encode(I18N::translate('Reload map')) ?>;
      let anchor        = L.DomUtil.create('a', 'leaflet-control-reset', container);
      anchor.setAttribute('aria-label', reset);
      anchor.href  = '#';
      anchor.title = reset;
      anchor.role  = 'button';
      let image    = L.DomUtil.create('i', 'fas fa-redo', anchor);
      image.alt    = reset;

      return container;
    },
  });

// Zoom control with localised text
  let newZoomControl = new L.control.zoom({
    zoomInTitle: <?= json_encode(I18N::translate('Zoom in')) ?>,
    zoomOutTitle: <?= json_encode(I18N::translate('Zoom out')) ?>,
  });

  /**
   *
   * @private
   */
  let _drawMap = function () {
    map = L.map('osm-map', {
      center:      [0, 0],
      minZoom:     minZoom,   // maxZoom set by leaflet-providers.js
      zoomControl: false,     // remove default
    })
    .addControl(new resetControl())
    .addControl(newZoomControl)
    .addLayer(L.tileLayer(provider.url, provider.options));
  };

  /**
   * @private
   */
  let _buildMapData = function () {
    let sidebar_content = '';
    let geoJson_data    = <?= json_encode($data) ?>;

    if (geoJson_data.features.length === 0) {
      map.fitWorld();
      sidebar_content += '<div class="bg-info text-white text-center">' + <?= json_encode(I18N::translate('Nothing to show')) ?> +'</div>';
    } else {
      if (geoJson_data.features.length === 1) {
        //fudge factor - maps zooms to maximum permitted otherwise
        zoom = geoJson_data.features[0].properties.zoom;
      }
      let geoJsonLayer = L.geoJson(geoJson_data, {
        pointToLayer:  function (feature, latlng) {
          return new L.Marker(latlng, {
            icon:  L.BeautifyIcon.icon({
              icon:            'bullseye fas',
              borderColor:     'transparent',
              backgroundColor: feature.properties.iconcolor,
              iconShape:       'marker',
              textColor:       'white',
            }),
            title: feature.properties.tooltip,
            alt:   feature.properties.tooltip,
            id:    feature.id,
          })
          .on('popupopen', function (e) {
            let item = sidebar.children('.gchart[data-id=' + e.target.feature.id + ']');
            item.addClass('messagebox');
            sidebar.scrollTo(item);
          })
          .on('popupclose', function () {
            sidebar.children('.gchart').removeClass('messagebox');
          });
        },
        onEachFeature: function (feature, layer) {
          if (feature.properties.polyline) {
            let pline = L.polyline(feature.properties.polyline.points, feature.properties.polyline.options);
            markers.addLayer(pline);
          }
          layer.bindPopup(feature.properties.summary);
          sidebar_content += `<li class="gchart px-md-2" data-id=${feature.id}>${feature.properties.summary}</li>`;
        },
      });
      markers.addLayer(geoJsonLayer);
      map.addLayer(markers);
      if (zoom) {
        map.setView(markers.getBounds().getCenter(), zoom);
      } else {
        map.fitBounds(markers.getBounds(), {padding: [50, 30]});
      }
    }
    sidebar.append(sidebar_content);
  };

  /**
   * @param   elem
   * @returns {$}
   */
  $.fn.scrollTo = function (elem) {
    let _this = $(this);
    _this.animate({
      scrollTop: elem.offset().top - _this.offset().top + _this.scrollTop(),
    });
    return this;
  };

// Activate marker popup when sidebar entry clicked
  $(function () {
    sidebar
    // open marker popup if sidebar event is clicked
    .on('click', '.gchart', function (e) {
      // first close any existing
      map.closePopup();
      let eventId  = $(this).data('id');
      //find the marker corresponding to the clicked event
      let mkrLayer = markers.getLayers().filter(function (v) {
        return typeof (v.feature) !== 'undefined' && v.feature.id === eventId;
      });
      let mkr      = mkrLayer.pop();
      // Unfortunately zoomToShowLayer zooms to maxZoom
      // when all marker in a cluster have exactly the
      // same co-ordinates
      markers.zoomToShowLayer(mkr, function (e) {
        mkr.openPopup();
      });

      return false;
    })
    .on('click', 'a', function (e) { // stop click on a person also opening the popup
      e.stopPropagation();
    });
  });

  _drawMap();
  _buildMapData();

  return 'Leaflet map interface for webtrees-2';
})();
</script>
<?php View::endpush() ?>
