/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.giannoules.proxstor.connection;


import com.giannoules.proxstor.api.Device;
import com.giannoules.proxstor.api.User;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import org.glassfish.jersey.moxy.xml.MoxyXmlFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class ProxStorConnector {

    WebTarget target;
    Gson gson;

    public ProxStorConnector(String path) {
        final Map<String, Object> properties = new HashMap<>();
        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        final ResourceConfig config = new ResourceConfig()                
                .register(new MoxyXmlFeature(
                                properties,
                                classLoader,
                                true,
                                User.class));
        target = ClientBuilder.newClient().target(path);
        gson = new Gson();
    }
    
    public User getUser(Integer userId) {
        return target.path("users/" + userId)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .get(User.class);
    }

    public Collection<User> searchUsers(User search) {
        String json = target.path("search/users")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.entity(search, MediaType.APPLICATION_JSON_TYPE), String.class);
        
        Type collectionType = new TypeToken<Collection<User>>() {}.getType();
        Collection<User> users = gson.fromJson(json, collectionType);

        return users;
    }

    public User putUser(User u) {
        return target.path("/users")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.entity(u, MediaType.APPLICATION_JSON_TYPE), User.class);
    }
    
    public void userKnows(User u, User v, int strength) {
        String path = "users/" + u.getUserId() + "/knows/" + strength + "/" + v.getUserId();
        target.path(path)
                .request(MediaType.TEXT_PLAIN)
                .post(null);
    }
    
    public Device getDevice(Integer userId, Integer devId) {
        return target.path("/users/" + userId + "/devices/" + devId)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .get(Device.class);
    }
    
    public Collection<Device> getDevices(Integer userId) {
        String json = target.path("/users/" + userId + "/devices")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .get(String.class);
        
        Type collectionType = new TypeToken<Collection<Device>>() {}.getType();
        Collection<Device> devices = gson.fromJson(json, collectionType);
        
        return devices;
    }
    
    public Device putDevice(Integer userId, Device dev) throws Exception {
        try {
        return target.path("/users/" + userId + "/devices/")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.entity(dev, MediaType.APPLICATION_JSON_TYPE), Device.class);
        } catch (javax.ws.rs.InternalServerErrorException ex) {
            throw new Exception("Cannot add " + dev + " to " + userId);
        }
    }
    
}
 
@@ -267,16 +267,104 @@
 Device;%0A
+import com.giannoules.proxstor.api.Location;%0Aimport com.giannoules.proxstor.api.Sensor;%0A
 import c
@@ -392,24 +392,24 @@
 r.api.User;%0A
-
 import com.g
@@ -2327,36 +2327,274 @@
 r.class);%0A    %7D%0A
+%0A
     
+public Location putLocation(Location l) %7B%0A        return target.path(%22/locations%22)%0A                .request(MediaType.APPLICATION_JSON_TYPE)%0A                .post(Entity.entity(l, MediaType.APPLICATION_JSON_TYPE), Location.class);%0A    %7D%0A
 %0A    public void
@@ -3954,16 +3954,1019 @@
 %7D%0A    %7D%0A
-
     %0A
+    public Sensor putSensor(Integer locId, Sensor s) throws Exception %7B%0A        try %7B%0A            return target.path(%22/locations/%22 + locId + %22/sensors/%22)%0A                    .request(MediaType.APPLICATION_JSON_TYPE)%0A                    .post(Entity.entity(s, MediaType.APPLICATION_JSON_TYPE), Sensor.class);%0A        %7D catch (javax.ws.rs.InternalServerErrorException ex) %7B%0A            throw new Exception(%22Cannot add %22 + s + %22 to %22 + locId);%0A        %7D%0A    %7D%0A    %0A    public void locationWithin(Location locA, Location locB) %7B%0A        String path = %22locations/%22 + locA.getLocId() + %22/within/%22 + locB.getLocId();%0A        target.path(path)%0A                .request(MediaType.TEXT_PLAIN)%0A                .post(null);%0A    %7D%0A    %0A      %0A    public void locationNearby(Location locA, Location locB, int d) %7B%0A        String path = %22locations/%22 + locA.getLocId() + %22/nearby/%22 + d + %22/%22 + locB.getLocId();%0A        target.path(path)%0A                .request(MediaType.TEXT_PLAIN)%0A                .post(null);%0A    %7D%0A
 %7D%0A 

support adding location within location and adding sensor