text: import GoogleMapsLoader from 'google-maps';
  
  import {GMapsLayerView, GMapsLayerModel} from './GMapsLayer';
  
  export class SimpleHeatmapLayerModel extends GMapsLayerModel {
      defaults() {
          return {
              ...super.defaults(),
              _view_name: 'SimpleHeatmapLayerView',
              _model_name: 'SimpleHeatmapLayerModel',
          };
      }
  }
  
  export class WeightedHeatmapLayerModel extends GMapsLayerModel {
      defaults() {
          return {
              ...super.defaults(),
              _view_name: 'WeightedHeatmapLayerView',
              _model_name: 'WeightedHeatmapLayerModel',
          };
      }
  }
  
  class HeatmapLayerBaseView extends GMapsLayerView {
      constructor(options) {
          super(options);
          this.canDownloadAsPng = true;
      }
  
      render() {
          this.modelEvents();
          GoogleMapsLoader.load(google => {
              this.heatmap = new google.maps.visualization.HeatmapLayer({
                  data: this.getData(),
                  radius: this.model.get('point_radius'),
                  maxIntensity: this.model.get('max_intensity'),
                  dissipating: this.model.get('dissipating'),
                  opacity: this.model.get('opacity'),
                  gradient: this.model.get('gradient'),
              });
          });
      }
  
      resetData() {
          this.heatmap.setData(this.getData());
      }
  
      addToMapView(mapView) {
          this.heatmap.setMap(mapView.map);
      }
  
      modelEvents() {
          // Simple properties:
          // [nameInView, nameInModel]
          const properties = [
              ['maxIntensity', 'max_intensity'],
              ['opacity', 'opacity'],
              ['radius', 'point_radius'],
              ['dissipating', 'dissipating'],
              ['gradient', 'gradient'],
          ];
          properties.forEach(([nameInView, nameInModel]) => {
              const callback = () =>
                  this.heatmap.set(nameInView, this.model.get(nameInModel));
              this.model.on(`change:${nameInModel}`, callback, this);
          });
      }
  }
  
  export class SimpleHeatmapLayerView extends HeatmapLayerBaseView {
      modelEvents() {
          super.modelEvents();
          this.model.on('change:locations', this.resetData, this);
      }
  
      getData() {
          const data = this.model.get('locations');
          const dataAsGoogle = new google.maps.MVCArray(
              data.map(([lat, lng]) => new google.maps.LatLng(lat, lng))
          );
          return dataAsGoogle;
      }
  }
  
  export class WeightedHeatmapLayerView extends HeatmapLayerBaseView {
      modelEvents() {
          super.modelEvents();
          this.model.on('change:locations', this.resetData, this);
          this.model.on('change:weights', this.resetData, this);
      }
  
      getData() {
          const data = this.model.get('locations');
          const weights = this.model.get('weights');
          const dataAsGoogle = new google.maps.MVCArray(
              data.map(([lat, lng], i) => {
                  const weight = weights[i];
                  const location = new google.maps.LatLng(lat, lng);
                  return {location, weight};
              })
          );
          return dataAsGoogle;
      }
  }
  