content: /*
   * Copyright 2012, 2013 Hannes Janetzek
   * Copyright 2017 Wolfgang Schramm
   * Copyright 2017-2018 devemux86
   * Copyright 2017 Andrey Novikov
   * Copyright 2018 Gustl22
   *
   * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
   *
   * This program is free software: you can redistribute it and/or modify it under the
   * terms of the GNU Lesser General Public License as published by the Free Software
   * Foundation, either version 3 of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT ANY
   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
   * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License along with
   * this program. If not, see <http://www.gnu.org/licenses/>.
   */
  package org.oscim.layers.tile.vector.labeling;
  
  import org.oscim.core.MapPosition;
  import org.oscim.event.Event;
  import org.oscim.layers.Layer;
  import org.oscim.layers.tile.MapTile;
  import org.oscim.layers.tile.TileManager;
  import org.oscim.layers.tile.ZoomLimiter;
  import org.oscim.layers.tile.vector.VectorTileLayer;
  import org.oscim.map.Map;
  import org.oscim.map.Viewport;
  import org.oscim.utils.async.SimpleWorker;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  public class LabelLayer extends Layer implements Map.UpdateListener, TileManager.Listener,
          ZoomLimiter.IZoomLimiter {
  
      static final Logger log = LoggerFactory.getLogger(LabelLayer.class);
  
      static final String LABEL_DATA = LabelLayer.class.getName();
  
      private static final long MAX_RELABEL_DELAY = 100;
  
      // Sane default to allow render themes to work
      private static final int ZOOM_LIMIT = Viewport.MAX_ZOOM_LEVEL;
  
      private final LabelPlacement mLabelPlacer;
      private final Worker mWorker;
      private final ZoomLimiter mZoomLimiter;
  
      public LabelLayer(Map map, VectorTileLayer l) {
          this(map, l, new LabelTileLoaderHook());
      }
  
      public LabelLayer(Map map, VectorTileLayer l, VectorTileLayer.TileLoaderThemeHook h) {
          this(map, l, h, ZOOM_LIMIT);
      }
  
      public LabelLayer(Map map, VectorTileLayer l, VectorTileLayer.TileLoaderThemeHook h,
                        int zoomLimit) {
          super(map);
          l.getManager().events.bind(this);
          l.addHook(h);
  
          mZoomLimiter = new ZoomLimiter(l.getManager(), map.viewport().getMinZoomLevel(),
                  map.viewport().getMaxZoomLevel(), zoomLimit);
  
          mLabelPlacer = new LabelPlacement(map, l.tileRenderer(), mZoomLimiter);
          mWorker = new Worker(map);
          mRenderer = new TextRenderer(mWorker);
      }
  
      class Worker extends SimpleWorker<LabelTask> {
  
          public Worker(Map map) {
              super(map, 50, new LabelTask(), new LabelTask());
          }
  
          @Override
          public boolean doWork(LabelTask t) {
  
              if (mLabelPlacer.updateLabels(t)) {
                  mMap.render();
                  return true;
              }
  
              return false;
          }
  
          @Override
          public void cleanup(LabelTask t) {
          }
  
          @Override
          public void finish() {
              mLabelPlacer.cleanup();
          }
  
          @Override
          public synchronized boolean isRunning() {
              return mRunning;
          }
      }
  
      @Override
      public void addZoomLimit() {
          mZoomLimiter.addZoomLimit();
      }
  
      @Override
      public void removeZoomLimit() {
          mZoomLimiter.removeZoomLimit();
      }
  
      public void clearLabels() {
          mWorker.cancel(true);
      }
  
      public void update() {
          if (!isEnabled())
              return;
  
          mWorker.submit(MAX_RELABEL_DELAY);
      }
  
      @Override
      public void onDetach() {
          mWorker.cancel(true);
          super.onDetach();
      }
  
      @Override
      public void onMapEvent(Event event, MapPosition mapPosition) {
  
          if (event == Map.CLEAR_EVENT)
              mWorker.cancel(true);
  
          if (!isEnabled())
              return;
  
          if (event == Map.POSITION_EVENT)
              mWorker.submit(MAX_RELABEL_DELAY);
      }
  
      //    @Override
      //    public void onMotionEvent(MotionEvent e) {
      //        //    int action = e.getAction() & MotionEvent.ACTION_MASK;
      //        //    if (action == MotionEvent.ACTION_POINTER_DOWN) {
      //        //        multi++;
      //        //        mTextRenderer.hold(true);
      //        //    } else if (action == MotionEvent.ACTION_POINTER_UP) {
      //        //        multi--;
      //        //        if (multi == 0)
      //        //            mTextRenderer.hold(false);
      //        //    } else if (action == MotionEvent.ACTION_CANCEL) {
      //        //        multi = 0;
      //        //        log.debug("cancel " + multi);
      //        //        mTextRenderer.hold(false);
      //        //    }
      //    }
  
      @Override
      public void onTileManagerEvent(Event e, MapTile tile) {
          if (e == TileManager.TILE_LOADED) {
              if (tile.isVisible && isEnabled())
                  mWorker.submit(MAX_RELABEL_DELAY / 4);
              //log.debug("tile loaded: {}", tile);
          } else if (e == TileManager.TILE_REMOVED) {
              //log.debug("tile removed: {}", tile);
          }
      }
  
  }
  