package com.epimorphics.registry.notification;

import com.epimorphics.appbase.core.App;
import com.epimorphics.appbase.core.Startup;
import com.epimorphics.registry.core.Description;
import com.epimorphics.registry.core.Register;
import com.epimorphics.registry.core.Registry;
import com.epimorphics.registry.message.MessagingService;
import com.epimorphics.registry.message.ProcessIfChanges;
import com.epimorphics.registry.store.RegisterEntryInfo;
import com.epimorphics.registry.store.StoreAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class RegistryMonitorRegister implements RegistryMonitor.State, Startup {
    private static final String MONITOR_REGISTER = "/system/monitor"; // relative to base URI

    private Logger log = LoggerFactory.getLogger(RegistryMonitorRegister.class);
    private final List<String> registers = new ArrayList<>();

    @Override public void startup(App app) {
        Registry reg = app.getA(Registry.class);
        initMonitor(reg);

        String register = reg.getBaseURI() + MONITOR_REGISTER;
        MessagingService msgSvc = reg.getMessagingService();
        MessagingService.Process onMonitorChange = new ProcessIfChanges(msg -> initMonitor(reg), register);

        msgSvc.processMessages(onMonitorChange);
    }

    @Override public Boolean isMonitored(String targetUri) {
        return registers.stream().anyMatch(register ->
                targetUri.equals(register) || targetUri.startsWith(register + "/")
        );
    }

    private synchronized void initMonitor(Registry reg) {
        registers.clear();

        StoreAPI store = reg.getStore();
        String uri = reg.getBaseURI() + MONITOR_REGISTER;

        store.beginSafeRead();
        Description desc = store.getDescription(uri);
        if (desc instanceof Register) {
            Register register = desc.asRegister();
            List<RegisterEntryInfo> members = register.getMembers();
            members.stream().map(RegisterEntryInfo::getEntityURI).forEach(registers::add);
        } else {
            log.warn("System register " + uri + " does not exist - unable to monitor changes.");
        }

        store.endSafeRead();
    }
}

@@ -492,16 +492,237 @@
 oreAPI;%0A
+import com.epimorphics.registry.vocab.RegistryVocab;%0Aimport org.apache.jena.rdf.model.RDFNode;%0Aimport org.apache.jena.rdf.model.Resource;%0Aimport org.apache.jena.rdf.model.Statement;%0Aimport org.apache.jena.vocabulary.RDF;%0A
 import o
@@ -2225,76 +2225,61 @@
 ers.
-stream().map(RegisterEntryInfo::getEntityURI).forEach(registers::add
+forEach(member -%3E addMonitoredRegister(member, store)
 );%0A 
@@ -2398,24 +2398,24 @@
 %0A        %7D%0A%0A
-
         stor
@@ -2436,11 +2436,851 @@
 );%0A    %7D
+%0A%0A    private void addMonitoredRegister(RegisterEntryInfo entry, StoreAPI store) %7B%0A        Resource root = store.getDescription(entry.getEntityURI()).getRoot();%0A        if (root.hasProperty(RDF.type, RegistryVocab.MonitorSpec)) %7B%0A            Statement stmt = root.getProperty(RegistryVocab.monitors);%0A            if (stmt != null) %7B%0A                String monitor = stmt.getObject().asResource().getURI();%0A                registers.add(monitor);%0A                log.info(%22Monitoring register: %22 + monitor);%0A            %7D else %7B%0A                log.warn(%22Unable to add monitor entry %22 + entry.getItemURI() + %22: Resource must specify a reg:monitors value.%22);%0A            %7D%0A        %7D else %7B%0A            log.warn(%22Unable to add monitor entry %22 + entry.getItemURI() + %22: Resource must have a rdf:type value of reg:MonitorSpec.%22);%0A        %7D%0A    %7D
 %0A%7D%0A

Change monitored register state to use monitor spec entries instead of URI only entries