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

import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * User: twalcari
 * Date: 1/14/2015
 * Time: 11:03
 */
public class ImageMap<T> {

    private final URL imageUrl;

    private final Map<Bounds, T> selectableRegions = new HashMap<>();

    public ImageMap(URL imageUrl) {
        this.imageUrl = imageUrl;
    }


    public ImageMap(URL imageUrl, Map<Bounds, T> selectableRegions) {
        this.imageUrl = imageUrl;
        this.selectableRegions.putAll(selectableRegions);
    }

    public void addSelectableRegion(Bounds region, T item) {
        selectableRegions.put(region, item);
    }

    public URL getImageUrl() {
        return imageUrl;
    }

    public Optional<T> getItem(double x, double y) {
        for (Map.Entry<Bounds, T> entry : selectableRegions.entrySet()) {
            if (entry.getKey().contains(x, y)) {
                //   System.out.println(x + "," + y + " lies within " + entry.getKey());
                return Optional.of(entry.getValue());
            }
        }
        //System.out.println(x + "," + y + " lies within nothing");
        return Optional.empty();
//
//        return selectableRegions.entrySet().stream()
//                .filter(entry -> entry.getKey().contains(x, y))
//                .map(Map.Entry::getValue).findFirst();
    }

    public Map<Bounds, T> getSelectableRegions() {
        return selectableRegions;
    }


    public Optional<Bounds> getSelectableRegion(T item) {
        return selectableRegions.entrySet().stream()
                .filter(entry -> Objects.equals(entry.getValue(), item))
                .map(Map.Entry::getKey)
                .findAny();
    }


    public static final class Bounds {

        private final double minX, maxX, minY, maxY;

        public Bounds(double minX, double maxX, double minY, double maxY) {
            this.minX = minX;
            this.maxX = maxX;
            this.minY = minY;
            this.maxY = maxY;
        }

        public boolean contains(double x, double y) {
            return x >= minX && x <= maxX && y >= minY && y <= maxY;
        }


        public double getMaxX() {
            return maxX;
        }

        public double getMaxY() {
            return maxY;
        }

        public double getMinX() {
            return minX;
        }

        public double getMinY() {
            return minY;
        }

        @Override
        public String toString() {
            return "[{" + minX + "," + minY + "},{" + maxX + "," + maxY + "}]";
        }

    }
}
