001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.plugins.streetside.cubemap;
003
004import java.awt.image.BufferedImage;
005import java.util.HashMap;
006import java.util.List;
007import java.util.Map;
008import java.util.Objects;
009import java.util.concurrent.Callable;
010import java.util.concurrent.CopyOnWriteArrayList;
011
012import javax.imageio.ImageIO;
013
014import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache;
015import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL;
016import org.openstreetmap.josm.tools.I18n;
017import org.openstreetmap.josm.tools.Logging;
018
019import us.monoid.web.Resty;
020
021public class TileDownloadingTask implements Callable<String> {
022
023        private String tileId;
024        private final long startTime = System.currentTimeMillis();
025        private StreetsideCache cache;
026        protected CubemapBuilder cb;
027
028        /**
029           * Listeners of the class.
030           */
031    private final List<ITileDownloadingTaskListener> listeners = new CopyOnWriteArrayList<>();
032
033        boolean cancelled = false;
034
035        public TileDownloadingTask(String id) {
036                tileId = id;
037                cb = CubemapBuilder.getInstance();
038                addListener(CubemapBuilder.getInstance());
039        }
040
041        /**
042           * Adds a new listener.
043           *
044           * @param lis Listener to be added.
045           */
046        public final void addListener(final ITileDownloadingTaskListener lis) {
047            listeners.add(lis);
048        }
049
050        /**
051         * @return the tileId
052         */
053        public String getId() {
054                return tileId;
055        }
056
057        /**
058         * @param id the tileId to set
059         */
060        public void setId(String id) {
061                tileId = id;
062        }
063
064        /**
065         * @return the cache
066         */
067        public StreetsideCache getCache() {
068                return cache;
069        }
070
071        /**
072         * @param cache the cache to set
073         */
074        public void setCache(StreetsideCache cache) {
075                this.cache = cache;
076        }
077
078        /**
079         * @return the cb
080         */
081        public CubemapBuilder getCb() {
082                return cb;
083        }
084
085        /**
086         * @param cb the cb to set
087         */
088        public void setCb(CubemapBuilder cb) {
089                this.cb = cb;
090        }
091
092        /**
093         * @param cancelled the cancelled to set
094         */
095        public void setCancelled(boolean cancelled) {
096                this.cancelled = cancelled;
097        }
098
099        @Override
100        public String call() throws Exception {
101
102                BufferedImage img = ImageIO.read(new Resty().bytes(
103                                StreetsideURL.VirtualEarth.streetsideTile(tileId, false).toExternalForm())
104                                .stream());
105
106                if (img == null) {
107                        Logging.error(I18n.tr("Download of BufferedImage {0} is null!", tileId));
108                }
109
110                String faceId = CubemapUtils.getFaceIdFromTileId(tileId);
111
112                Map<String, Map<String, BufferedImage>> faces2TilesMap = CubemapBuilder
113                                .getInstance().getCubemap().getFace2TilesMap();
114
115                if(faces2TilesMap.get(faceId)==null) {
116                        faces2TilesMap.put(faceId, new HashMap<String,BufferedImage>());
117                }
118                faces2TilesMap.get(faceId).put(tileId, img);
119
120                fireTileAdded(tileId);
121
122                long endTime = System.currentTimeMillis();
123                long runTime = startTime - endTime;
124                Logging.debug("Loaded image for tile {0} in {1} seconds", tileId, CubemapUtils.msToString(runTime));
125
126                return tileId;
127        }
128
129        private void fireTileAdded(String id) {
130            listeners.stream().filter(Objects::nonNull).forEach(lis -> lis.tileAdded(id));
131        }
132}