package cgeo.geocaching.maps.mapsforge.v6.caches;

import org.mapsforge.map.layer.Layer;

import android.support.annotation.NonNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

public class GeoitemLayers implements Collection<GeoitemLayer> {

    private final HashMap<String, GeoitemLayer> geoitems = new HashMap<>();

    public Collection<String> getGeocodes() {
        return new ArrayList<>(geoitems.keySet());
    }

    public Collection<Layer> getAsLayers() {
        return new ArrayList<Layer>(this.geoitems.values());
    }

    public GeoitemLayer getItem(final String itemCode) {
        return geoitems.get(itemCode);
    }

    public Collection<Layer> getMatchingLayers(final Collection<String> newCodes) {
        final ArrayList<Layer> result = new ArrayList<>();
        for (final String code : newCodes) {
            if (geoitems.containsKey(code)) {
                result.add(geoitems.get(code));
            }
        }
        return result;
    }

    @Override
    public boolean add(final GeoitemLayer geoitem) {
        return geoitems.put(geoitem.getItemCode(), geoitem) != null;
    }

    @Override
    public boolean addAll(@NonNull final Collection<? extends GeoitemLayer> geoitemsIn) {
        boolean result = true;
        for (final GeoitemLayer geoitem : geoitemsIn) {
            if (!this.add(geoitem)) {
                result = false;
            }
        }
        return result;
    }

    @Override
    public void clear() {
        this.geoitems.clear();
    }

    @Override
    public boolean contains(final Object object) {
        return this.geoitems.containsValue(object);
    }

    @Override
    public boolean containsAll(@NonNull final Collection<?> items) {
        return this.geoitems.values().containsAll(items);
    }

    @Override
    public boolean isEmpty() {
        return this.geoitems.isEmpty();
    }

    @Override
    @NonNull
    public Iterator<GeoitemLayer> iterator() {
        return this.geoitems.values().iterator();
    }

    @Override
    public boolean remove(final Object object) {
        if (object instanceof GeoitemLayer) {
            final GeoitemLayer item = (GeoitemLayer) object;
            return this.geoitems.remove(item.getItem().getItemCode()) != null;

        }

        return false;
    }

    @Override
    public boolean removeAll(@NonNull final Collection<?> items) {
        boolean result = true;
        for (final Object item : items) {
            if (!this.remove(item)) {
                result = false;
            }
        }
        return result;
    }

    @Override
    public boolean retainAll(@NonNull final Collection<?> items) {

        return this.geoitems.values().retainAll(items);
    }

    @Override
    public int size() {

        return this.geoitems.size();
    }

    @Override
    @NonNull
    public Object[] toArray() {

        return this.geoitems.values().toArray();
    }

    @SuppressWarnings("hiding")
    @Override
    @NonNull
    public <GeoitemLayer> GeoitemLayer[] toArray(@NonNull final GeoitemLayer[] array) {

        return this.geoitems.values().toArray(array);
    }

}

@@ -48,47 +48,8 @@
 s;%0A%0A
-import org.mapsforge.map.layer.Layer;%0A%0A
 impo
@@ -199,16 +199,55 @@
 rator;%0A%0A
+import org.mapsforge.map.layer.Layer;%0A%0A
 public c
@@ -384,32 +384,45 @@
 ();%0A%0A    public 
+synchronized 
 Collection%3CStrin
@@ -501,32 +501,45 @@
   %7D%0A%0A    public 
+synchronized 
 Collection%3CLayer
@@ -635,16 +635,29 @@
  public 
+synchronized 
 GeoitemL
@@ -751,16 +751,29 @@
  public 
+synchronized 
 Collecti
@@ -1093,36 +1093,23 @@
  %7D%0A%0A    
-@Override%0A    public
+private
  boolean
@@ -1112,16 +1112,24 @@
 lean add
+Internal
 (final G
@@ -1244,32 +1244,169 @@
 ride%0A    public 
+synchronized boolean add(final GeoitemLayer geoitem) %7B%0A        return addInternal(geoitem);%0A    %7D%0A%0A    @Override%0A    public synchronized 
 boolean addAll(@
@@ -1576,24 +1576,32 @@
 f (!this.add
+Internal
 (geoitem)) %7B
@@ -1712,16 +1712,29 @@
  public 
+synchronized 
 void cle
@@ -1795,32 +1795,45 @@
 ride%0A    public 
+synchronized 
 boolean contains
@@ -1932,32 +1932,45 @@
 ride%0A    public 
+synchronized 
 boolean contains
@@ -2093,32 +2093,45 @@
 ride%0A    public 
+synchronized 
 boolean isEmpty(
@@ -2219,16 +2219,29 @@
  public 
+synchronized 
 Iterator
@@ -2275,32 +2275,48 @@
 %0A        return 
+new ArrayList%3C%3E(
 this.geoitems.va
@@ -2321,16 +2321,17 @@
 values()
+)
 .iterato
@@ -2346,36 +2346,23 @@
  %7D%0A%0A    
-@Override%0A    public
+private
  boolean
@@ -2368,16 +2368,24 @@
 n remove
+Internal
 (final O
@@ -2644,32 +2644,167 @@
 ride%0A    public 
+synchronized boolean remove(final Object object) %7B%0A        return removeInternal(object);%0A    %7D%0A%0A    @Override%0A    public synchronized 
 boolean removeAl
@@ -2940,24 +2940,32 @@
 !this.remove
+Internal
 (item)) %7B%0A  
@@ -3073,16 +3073,29 @@
  public 
+synchronized 
 boolean 
@@ -3231,16 +3231,29 @@
  public 
+synchronized 
 int size
@@ -3340,16 +3340,29 @@
  public 
+synchronized 
 Object%5B%5D
@@ -3501,16 +3501,29 @@
  public 
+synchronized 
 %3CGeoitem

Fix #5907, Concurrent modification exception in new map