import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.CoapServer;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.server.resources.CoapExchange;

public class Main {
    public static void main(String[] args) {
        var server = new CoapServer(5683);
        server.add(new HelloWorldResource());
        server.add(new TimeResource());
        server.add(new SubPathResource());
        server.add(new ModifiableResource());
        server.add(new DeletableResource());
        server.add(new LightResource());
        server.start();
    }
}


class HelloWorldResource extends CoapResource {
    public HelloWorldResource() {
        super("hello-world");
    }

    @Override
    public void handleGET(CoapExchange exchange) {
        exchange.respond(CoAP.ResponseCode.CONTENT, "hello world");
    }
}


class TimeResource extends CoapResource {
    public TimeResource() {
        super("time");
    }

    @Override
    public void handleGET(CoapExchange exchange) {
        exchange.respond(CoAP.ResponseCode.CONTENT, Long.toString(System.currentTimeMillis()));
    }
}


class SubPathResource extends CoapResource {
    public SubPathResource() {
        super("subpath");
        add(new AnotherResource());
    }

    @Override
    public void handleGET(CoapExchange exchange) {
        exchange.respond(CoAP.ResponseCode.CONTENT, "subpath");
    }
}


class AnotherResource extends CoapResource {
    public AnotherResource() {
        super("another");
    }

    @Override
    public void handleGET(CoapExchange exchange) {
        exchange.respond(CoAP.ResponseCode.CONTENT, "another");
    }
}


class ModifiableResource extends CoapResource {
    private String value;
    public ModifiableResource() {
        super("modifiable");
        value = "Start";
    }

    @Override
    public void handleGET(CoapExchange exchange) {
        exchange.respond(CoAP.ResponseCode.CONTENT, value);
    }

    @Override
    public void handlePUT(CoapExchange exchange) {
        value = exchange.getRequestText();
        exchange.respond(CoAP.ResponseCode.CHANGED, value);
    }
}


class DeletableResource extends CoapResource {
    public DeletableResource() {
        super("deletable");
    }

    @Override
    public void handleGET(CoapExchange exchange) {
        exchange.respond(CoAP.ResponseCode.DELETED, "Deleted resource.");
    }
}


class LightResource extends CoapResource {
    public LightResource() {
        super("Light");
        brightness = 6;
        add(new LampResource());
        setObservable(true);
    }

    Integer brightness;

    @Override
    public void handleGET(CoapExchange exchange) {
        System.out.println("access detected");
        exchange.respond(CoAP.ResponseCode.CONTENT, brightness.toString());
    }

    @Override
    public void handlePUT(CoapExchange exchange) {
        brightness = Integer.parseInt(exchange.getRequestText());
        exchange.respond(CoAP.ResponseCode.CHANGED, brightness.toString());
    }
}

enum LampState {
    On("On"),
    Off("Off");

    private String text;
    private LampState(String text_) {
        text = text_;
    }

    @Override
    public String toString() {
        return text;
    }

    public static LampState fromString(String text_) {
        if (text_.equals("On")) return LampState.On;
        if (text_.equals("Off")) return LampState.Off;
        return null;
    }
}

class LampResource extends CoapResource {
    private LampState state = LampState.On;
    public LampResource() {
        super("lamp");
    }

    @Override
    public void handlePUT(CoapExchange exchange) {
        var input = LampState.fromString(exchange.getRequestText());
        if (input == null) return;
        exchange.respond(CoAP.ResponseCode.CHANGED, state.toString());
    }
}