package be.iminds.ilabt.jfed.experimenter_gui.editor.properties.map;

import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Resource;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.ResourceClass;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.Server;
import com.lynden.gmapsfx.ClusteredGoogleMapView;
import com.lynden.gmapsfx.MapComponentInitializedListener;
import com.lynden.gmapsfx.javascript.event.UIEventType;
import com.lynden.gmapsfx.javascript.object.*;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Properties;

/**
 * User: twalcari
 * Date: 1/8/2015
 * Time: 14:34
 */
public class TestbedsMapDialog implements MapComponentInitializedListener {
    private static final Logger LOG = LoggerFactory.getLogger(TestbedsMapDialog.class);

    private static final String PROP_GOOGLE_APIKEY = "google.apiKey";
    private static final String API_KEYS_PROPERTIES = "/api-keys.properties";

    private ClusteredGoogleMapView mapView;

    @FXML
    private BorderPane root;
    @FXML
    private Label testbedNameLabel;
    @FXML
    private Label testbedCountryLabel;
    @FXML
    private Button selectTestbedButton;

    private boolean mapViewIsInitialized = false;

    private ClusteredGoogleMap map;

    private ResourceClass resourceClass = null;

    private final ObjectProperty<Resource> selectedResource = new SimpleObjectProperty<>();
    private Resource result = null;

    @FXML
    private void initialize() {
        Properties prop = new Properties();
        //now load the version-properties file
        try {
            prop.load(getClass().getResourceAsStream(API_KEYS_PROPERTIES));
        } catch (IOException e) {
            throw new RuntimeException("Something went wrong fetching the API keys file: " + e.getMessage(), e);

        }


        mapView = new ClusteredGoogleMapView("en", prop.getProperty(PROP_GOOGLE_APIKEY, null));
        mapView.addMapInializedListener(this);

        root.setCenter(mapView);


        selectTestbedButton.disableProperty().bind(selectedResource.isNull());
    }

    @Override
    public void mapInitialized() {
        mapViewIsInitialized = true;

        tryInitializeMap();


    }

    private void tryInitializeMap() {
        if (resourceClass == null) return;
        if (!mapViewIsInitialized) return;

        MapOptions mapOptions = new MapOptions();

        mapOptions.mapType(MapTypeIdEnum.ROADMAP)
                .center(new LatLong(47.56, 372))
                .overviewMapControl(true)
                .panControl(true)
                .rotateControl(true)
                .scaleControl(true)
                .streetViewControl(true)
                .zoomControl(true)
                .zoom(2);

        map = mapView.createMap(mapOptions);

        map.getMarkerClusterer().setGridSize(20);

        LatLongBounds bounds = new LatLongBounds();

        for (final Resource curResource : resourceClass.getResources()) {
            Server auth = curResource.getServer();
            if (auth.getLocation() != null) {
                LatLong authLatLong =
                        new LatLong(auth.getLocation().getLatitude(), auth.getLocation().getLongitude());

                bounds.extend(authLatLong);

                MarkerOptions authMarkerOptions = new MarkerOptions();
                authMarkerOptions.position(authLatLong);
                authMarkerOptions.title(auth.getName());

                Marker authMarker = new Marker(authMarkerOptions);

                LOG.info("Adding marker {} at location {}", auth.getName(), auth.getLocation());

                map.addClusterableMarker(authMarker);

                map.addUIEventHandler(authMarker, UIEventType.click, obj -> selectTestbed(curResource));
            }
        }

       // map.fitBounds(bounds);
    }

    private void selectTestbed(Resource resource) {
        Server auth = resource.getServer();
        map.panTo(new LatLong(auth.getLocation().getLatitude(), auth.getLocation().getLongitude()));

        testbedNameLabel.setText(auth.getName());
        String address = auth.getLocation().getAddress() == null ? "  Address: "+auth.getLocation().getAddress() : "";
        testbedCountryLabel.setText("Country: " + auth.getLocation().getCountryCode()+address);

        selectedResource.setValue(resource);
    }

    public void setCmiManager(ResourceClass resourceClass) {
        this.resourceClass = resourceClass;
        tryInitializeMap();
    }

    @FXML
    private void selectTestbed() {
        result = selectedResource.get();
        ((Stage) selectTestbedButton.getScene().getWindow()).close();
    }

    public Resource getResult() {
        return result;
    }
}
