diff --git a/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java b/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java
index a1c4c11af6426ae95dc08ab4a73954534d953c58..ea0da30d218de7b4773434fb95e51e7722d8078a 100644
--- a/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java
+++ b/src/main/java/NTNU/IDATT1002/controllers/ImageMapFactory.java
@@ -2,55 +2,65 @@ package NTNU.IDATT1002.controllers;
 
 import NTNU.IDATT1002.models.GeoLocation;
 import NTNU.IDATT1002.models.Image;
+import NTNU.IDATT1002.service.TagService;
+import NTNU.IDATT1002.utils.MetadataStringFormatter;
 import com.lynden.gmapsfx.GoogleMapView;
+import com.lynden.gmapsfx.javascript.event.UIEventType;
 import com.lynden.gmapsfx.javascript.object.*;
+import netscape.javascript.JSObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 
 /**
  * Class ImageMapFactory. Factory for map creation with markers for given images and default options.
- * Default center location is Berlin in order to center the full scale map onto a page.
+ * Default center location is Copenhagen in order to center the full scale map onto a page.
  *
  * @author Eirik Steira
  */
 public class ImageMapFactory {
 
-    private static Logger logger = LoggerFactory.getLogger(ImageMapFactory.class);
-
-    private ImageMapFactory() {}
+    private GoogleMap map;
+    private Logger logger = LoggerFactory.getLogger(ImageMapFactory.class);
+    private Map<LatLong, Image> latLongImageMapping = new HashMap<>();
+    
+    public ImageMapFactory() {
+    }
 
     /**
      * Create a map from given {@link GoogleMapView} with default options.
      *
-     * @param googleMapView the map view to add the map to
+     * @param mapView the map view to add the map to
      * @return the {@link GoogleMap} created to enable further customization
      */
-    public static GoogleMap createMap(GoogleMapView googleMapView) {
+    public GoogleMap createMap(GoogleMapView mapView) {
         MapOptions mapOptions = getMapOptions();
-        return googleMapView.createMap(mapOptions);
+        map = mapView.createMap(mapOptions);
+        logger.info("[x] Map created");
+        return map;
     }
 
     /**
      * Create default {@link MapOptions} to be applied to a map. Extend this for further marker customizations.
-     * The default center location is Berlin to get a look of the entire map when the zoom is set to fit the window.
+     * The default center location is Copenhagen to get a look of the entire map when the zoom is set to fit the window.
      *
      * @return the default map options
      */
-    private static MapOptions getMapOptions() {
-        LatLong berlin = new LatLong(52.520008, 13.404954);
+    private MapOptions getMapOptions() {
+        LatLong copenhagen = new LatLong(55.676098, 12.568337);
         return new MapOptions()
-                .center(berlin)
+                .center(copenhagen)
                 .mapType(MapTypeIdEnum.ROADMAP)
                 .overviewMapControl(false)
                 .panControl(false)
-                .rotateControl(false)
-                .scaleControl(false)
                 .streetViewControl(false)
-                .zoomControl(false)
+                .zoomControl(true)
                 .zoom(3);
     }
 
@@ -60,7 +70,7 @@ public class ImageMapFactory {
      * @param images the list of images
      * @return a list of markers created from the images
      */
-    public static List<Marker> createMarkers(List<Image> images) {
+    public List<Marker> createMarkers(List<Image> images) {
         List<LatLong> locations = getLatLongs(images);
         List<Marker> markers = getMarkers(locations);
         logger.info("[x] {} markers created", markers.size());
@@ -73,16 +83,27 @@ public class ImageMapFactory {
      * @param images the list of images
      * @return a list of {@link LatLong}
      */
-    private static List<LatLong> getLatLongs(List<Image> images) {
+    private List<LatLong> getLatLongs(List<Image> images) {
         return images.stream()
-                .map(Image::getGeoLocation)
-                .filter(GeoLocation::hasLatLong)
-                .map(geoLocation -> {
-                    double latitude = Double.parseDouble(geoLocation.getLatitude());
-                    double longitude = Double.parseDouble(geoLocation.getLongitude());
-                    return new LatLong(latitude, longitude);
-                })
-                .collect(Collectors.toList());
+            .filter(image -> image.getGeoLocation().hasLatLong())
+            .map(image -> {
+                LatLong latLong = getLatLong(image);
+                latLongImageMapping.put(latLong, image);
+                return latLong;
+            }).collect(Collectors.toList());
+    }
+
+    /**
+     * Get a {@link LatLong} from a single image.
+     *
+     * @param image the image holding the {@link GeoLocation}
+     * @return the {@link LatLong} created
+     */
+    private LatLong getLatLong(Image image) {
+        GeoLocation geoLocation = image.getGeoLocation();
+        double latitude = Double.parseDouble(geoLocation.getLatitude());
+        double longitude = Double.parseDouble(geoLocation.getLongitude());
+        return new LatLong(latitude, longitude);
     }
 
     /**
@@ -91,15 +112,58 @@ public class ImageMapFactory {
      * @param locations the list containing the locations
      * @return the list of markers created
      */
-    private static List<Marker> getMarkers(List<LatLong> locations) {
+    private List<Marker> getMarkers(List<LatLong> locations) {
         return locations.stream()
-                .map(location -> {
-                    MarkerOptions markerOptions = new MarkerOptions()
-                            .position(location);
-                    logger.info("[x] Marker created for location: {}", location);
-                    return new Marker(markerOptions);
-                })
+                .map(this::getMarker)
                 .collect(Collectors.toList());
     }
 
+    /**
+     * Create {@link Marker} for given location with map zoom and center on click event.
+     *
+     * @param location the location of the marker
+     * @return marker created
+     */
+    private Marker getMarker(LatLong location) {
+        MarkerOptions markerOptions = new MarkerOptions()
+                .position(location)
+                .animation(Animation.DROP);
+
+        logger.info("[x] Marker created for location: {}", location);
+        Marker marker = new Marker(markerOptions);
+
+        InfoWindow infoWindow = getInfoWindow(location);
+        map.addUIEventHandler(marker, UIEventType.click, (JSObject obj) -> {
+           map.setZoom(10);
+           map.setCenter(location);
+           infoWindow.open(map, marker);
+        });
+
+        return marker;
+    }
+
+    /**
+     * Get {@link InfoWindow} with default options to display the
+     * corresponding image data.
+     *
+     * @param location the location corresponding to an image
+     * @return the {@link InfoWindow} created
+     */
+    private InfoWindow getInfoWindow(LatLong location) {
+        Image image = latLongImageMapping.get(location);
+
+        String username = image.getUser().getUsername();
+        String tags = TagService.getTagsAsString(image.getTags());
+        Date uploadedAt = image.getUploadedAt();
+        String metadata = MetadataStringFormatter.format(image.getMetadata(), "<br/>");
+
+        InfoWindowOptions infoWindowOptions = new InfoWindowOptions()
+                .content("<h3>Id: " + image.getId() + "</h3>" +
+                                 "<p><b>User:</b> " + username + "</p>" +
+                                 "<p><b>Tags:</b> " + tags + "</p>" +
+                                 "<p><b>Uploaded at:</b> " + uploadedAt + "</p>" +
+                                 "<p><b>Metadata:</b> <br/>" + metadata + "</p>");
+
+        return new InfoWindow(infoWindowOptions);
+    }
 }
diff --git a/src/main/java/NTNU/IDATT1002/controllers/Map.java b/src/main/java/NTNU/IDATT1002/controllers/Map.java
index f5057ae473335f78e13ead88b48907be845a2081..6aa64a2aa92178019ed787c0e1c842ad5d2d12f2 100644
--- a/src/main/java/NTNU/IDATT1002/controllers/Map.java
+++ b/src/main/java/NTNU/IDATT1002/controllers/Map.java
@@ -102,14 +102,15 @@ public class Map extends NavBarController implements Initializable, MapComponent
      */
     @Override
     public void mapInitialized() {
-        googleMap = ImageMapFactory.createMap(mapView);
+        ImageMapFactory imageMapFactory = new ImageMapFactory();
+        googleMap = imageMapFactory.createMap(mapView);
         
         Task<List<Image>> fetchImagesTask = getImageListTask();
         executorService.submit(fetchImagesTask);
 
         fetchImagesTask.setOnSucceeded(workerStateEvent -> {
             List<Image> images = fetchImagesTask.getValue();
-            List<Marker> markers = ImageMapFactory.createMarkers(images);
+            List<Marker> markers = imageMapFactory.createMarkers(images);
             googleMap.addMarkers(markers);
         });
     }
diff --git a/src/main/java/NTNU/IDATT1002/models/Image.java b/src/main/java/NTNU/IDATT1002/models/Image.java
index 1fdb682dafedb98fabd7cc8f25bf0660a13fbcde..7e994784c545ab55f0ce0a3bc9125fcc212b1a97 100644
--- a/src/main/java/NTNU/IDATT1002/models/Image.java
+++ b/src/main/java/NTNU/IDATT1002/models/Image.java
@@ -116,11 +116,10 @@ public class Image {
     return uploadedAt;
   }
 
-  public String getPath() {
-    return path;
+  public User getUser() {
+    return user;
   }
 
-
   /**
    * Add this image in the given album.
    *
diff --git a/src/main/java/NTNU/IDATT1002/models/Metadata.java b/src/main/java/NTNU/IDATT1002/models/Metadata.java
index a1fd351bf3dcfe07d8f1b0222c890a9d7d611450..e887712045ab2e5d29cd7805bc1274688dd25f15 100644
--- a/src/main/java/NTNU/IDATT1002/models/Metadata.java
+++ b/src/main/java/NTNU/IDATT1002/models/Metadata.java
@@ -61,6 +61,22 @@ public class Metadata {
     public Metadata() {
     }
 
+    public Metadata(Metadata metadata) {
+        this.metadataId = metadata.getMetadataId();
+        this.image = metadata.getImage();
+        this.geolocation = metadata.getGeoLocation();
+        this.camera = metadata.getCamera();
+        this.lens = metadata.getLens();
+        this.aperture = metadata.getAperture();
+        this.shutterSpeed = metadata.getShutterSpeed();
+        this.ISO = metadata.getISO();
+        this.focalLength = metadata.getFocalLength();
+        this.fileType = metadata.getFileType();
+        this.photoDate = metadata.getPhotoDate();
+        this.fileSize = metadata.getFileSize();
+        this.fileDimension = metadata.getFileDimension();
+    }
+
 
     public Long getMetadataId() {
         return metadataId;
diff --git a/src/main/java/NTNU/IDATT1002/utils/MetadataStringFormatter.java b/src/main/java/NTNU/IDATT1002/utils/MetadataStringFormatter.java
index 462392bd59a08ba3844e07ff7590d45c86d08df9..ce94455995c108e9b68b236a887fa2142b5d1860 100644
--- a/src/main/java/NTNU/IDATT1002/utils/MetadataStringFormatter.java
+++ b/src/main/java/NTNU/IDATT1002/utils/MetadataStringFormatter.java
@@ -1,5 +1,6 @@
 package NTNU.IDATT1002.utils;
 
+import NTNU.IDATT1002.models.GeoLocation;
 import NTNU.IDATT1002.models.Metadata;
 import org.apache.commons.text.WordUtils;
 import org.slf4j.Logger;
@@ -38,14 +39,15 @@ public class MetadataStringFormatter {
      * @param delimiter the delimiter separating the fields
      * @return the formatted string
      */
-    public static String format(Metadata metadata, char delimiter) {
+    public static String format(Metadata metadata, String delimiter) {
+        Metadata pureMetadata = new Metadata(metadata);
+        Stream<Field> fields = Arrays.stream(pureMetadata.getClass().getDeclaredFields());
 
-        Stream<Field> fields = Arrays.stream(metadata.getClass().getDeclaredFields());
         StringBuilder metadataString = new StringBuilder();
 
         fields.filter(field -> include.contains(field.getName()))
                 .forEach(field -> {
-                    String formattedField = getFormattedField(metadata, delimiter, field);
+                    String formattedField = getFormattedField(pureMetadata, delimiter, field);
                     metadataString.append(formattedField);
                 });
 
@@ -63,21 +65,17 @@ public class MetadataStringFormatter {
      * @return the formatted field as a string
      */
     private static String getFormattedField(Metadata metadata,
-                                            char delimiter,
+                                            String delimiter,
                                             Field field) {
         field.setAccessible(true);
 
         String[] fieldNameSplitByUppercase = field.getName().split("(?=\\p{Upper}[a-z])");
         String fieldNameTitle = String.join(" ", fieldNameSplitByUppercase);
 
-        StringBuilder fieldString = new StringBuilder();
-        fieldString.append(WordUtils.capitalizeFully(fieldNameTitle))
-                .append(": ");
-
-        fieldString.append(getFieldValue(metadata, field))
-                .append(delimiter);
-
-        return fieldString.toString();
+        return WordUtils.capitalizeFully(fieldNameTitle) +
+                ": " +
+                getFieldValue(metadata, field) +
+                delimiter;
     }
 
     /**
@@ -88,14 +86,9 @@ public class MetadataStringFormatter {
      */
     private static String getFieldValue(Metadata metadata, Field field) {
         StringBuilder fieldValueString = new StringBuilder();
+        
         try {
-            if (field.get(metadata) == null)
-                fieldValueString.append("No ")
-                        .append(field.getName())
-                        .append(" found.");
-            else
-                fieldValueString.append(field.get(metadata));
-
+            appendFieldValue(metadata, field, fieldValueString);
         } catch (IllegalAccessException e) {
             logger.error("[x] Failed to process field {}", field.getName(), e);
         }
@@ -103,4 +96,34 @@ public class MetadataStringFormatter {
         return fieldValueString.toString();
     }
 
+    /**
+     * Append given fields value from given metadata to given string builder.
+     *
+     * @param metadata the metadata object holding the data
+     * @param field the field to get the value from
+     * @param fieldValueString the StringBuilder to append to
+     * @throws IllegalAccessException if field does not exist or access is denied
+     */
+    private static void appendFieldValue(Metadata metadata, Field field, StringBuilder fieldValueString)
+            throws IllegalAccessException {
+        Object fieldValue = field.get(metadata);
+
+        if (fieldValue == null || fieldValue.equals(""))
+            fieldValueString.append("No ")
+                    .append(field.getName())
+                    .append(" found.");
+        else if (field.getName().equals("geolocation"))
+            fieldValueString.append(getGeoLocationValue(metadata, field));
+        else
+            fieldValueString.append(fieldValue);
+    }
+
+    private static String getGeoLocationValue(Metadata metadata, Field field) throws IllegalAccessException {
+        GeoLocation geolocation = (GeoLocation) field.get(metadata);
+        return "latitude: " +
+                geolocation.getLatitude() +
+                ", longitude: " +
+                geolocation.getLatitude();
+    }
+
 }
diff --git a/src/main/resources/NTNU/IDATT1002/map.fxml b/src/main/resources/NTNU/IDATT1002/map.fxml
index 9c352273a7df656dbcf8ceef0f566ad97b5ce616..9a4c1dfd80012657d7145fc72eae3549ed1e114a 100644
--- a/src/main/resources/NTNU/IDATT1002/map.fxml
+++ b/src/main/resources/NTNU/IDATT1002/map.fxml
@@ -76,7 +76,7 @@
                 <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="797.0" prefWidth="1920.0" style="-fx-background-color: #888888;" VBox.vgrow="ALWAYS">
                     <children>
 
-                        <GoogleMapView fx:id="mapView" prefHeight="750.0" prefWidth="761.0" AnchorPane.bottomAnchor="-185.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="-441.0" AnchorPane.topAnchor="0.0"/>
+                        <GoogleMapView fx:id="mapView" prefHeight="750.0" prefWidth="761.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/>
 
                     </children>
                 </AnchorPane>
diff --git a/src/test/java/NTNU/IDATT1002/utils/MetadataStringFormatterTest.java b/src/test/java/NTNU/IDATT1002/utils/MetadataStringFormatterTest.java
index ea13bcf6333f981db78212db34220bc9c8176a57..f1d39b0b693f88f72565444543ff634e2264bb56 100644
--- a/src/test/java/NTNU/IDATT1002/utils/MetadataStringFormatterTest.java
+++ b/src/test/java/NTNU/IDATT1002/utils/MetadataStringFormatterTest.java
@@ -27,7 +27,7 @@ class MetadataStringFormatterTest {
     @Disabled("Not able to solve CI test run failure on this test")
     @Test
     void testFormatReturnsFormattedString() {
-        String metadataString = MetadataStringFormatter.format(metadata, ' ');
+        String metadataString = MetadataStringFormatter.format(metadata, "");
 
         assertEquals(metadataString.trim(), formattedMetadata.trim());
     }