package org.purl.wf4ever.robundle.manifest;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.riot.RiotException;

import com.github.jsonldjava.jena.JenaJSONLD;
import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

public class RDFToManifest {
    private static final URI ROOT = URI.create("/");
    private static final String PROV = "http://www.w3.org/ns/prov#";
    private static final String PROV_O = "http://www.w3.org/ns/prov-o#";
    private static final String FOAF_0_1 = "http://xmlns.com/foaf/0.1/";
    private static final String PAV = "http://purl.org/pav/";

    private static final String RO = "http://purl.org/wf4ever/ro#";
    private static final String ORE = "http://www.openarchives.org/ore/terms/";
    private static final String FOAF_RDF = "/ontologies/foaf.rdf";
    private static final String PAV_RDF = "/ontologies/pav.rdf";
    private static final String PROV_O_RDF = "/ontologies/prov-o.rdf";
    private static final String PROV_AQ_RDF = "/ontologies/prov-aq.rdf";
    private OntModel ore;
    private ObjectProperty aggregates;
    private ObjectProperty proxyFor;
    private ObjectProperty proxyIn;

    private OntClass aggregation;
    private OntModel foaf;
    private DatatypeProperty foafName;
    private OntModel pav;
    private ObjectProperty createdBy;
    private OntModel prov;
    private OntModel provaq;
    private ObjectProperty hasProvenance;

    public RDFToManifest() {
        loadOntologies();
    }
    
    protected void loadOntologies() {
        loadORE();
        loadFOAF();
        loadPROVO();
        loadPAV();
        loadPROVAQ();
    }

    protected OntModel loadOntologyFromClasspath(String classPathUri, String uri) {
        OntModel ontModel = ModelFactory.createOntologyModel();

        // Load from classpath
        InputStream inStream = getClass().getResourceAsStream(classPathUri);
        if (inStream == null) {
            throw new IllegalArgumentException("Can't load " + classPathUri);
        }
//        Ontology ontology = ontModel.createOntology(uri);
        ontModel.read(inStream, uri);
        return ontModel;
    }


    
    
    protected static Model jsonLdAsJenaModel(InputStream jsonIn, URI base) throws IOException,
            RiotException {
        JenaJSONLD.init();
        Model model = ModelFactory.createDefaultModel();
        RDFDataMgr.read(model, jsonIn, base.toASCIIString(), JenaJSONLD.JSONLD);
        return model;
        
//        
//        Object input = JSONUtils.fromInputStream(jsonIn);
//        JSONLDTripleCallback callback = new JenaTripleCallback();        
//        Model model = (Model)JSONLD.toRDF(input, callback, new Options(base.toASCIIString()));
//        return model;
    }
    
    private void checkNotNull(Object... possiblyNulls) {
        int i=0;
        for (Object check : possiblyNulls) {
            if (check == null) {
                throw new IllegalStateException("Could not load item #" + i);
            }
            i++;
        }
        
    }


    protected OntModel getOntModel() {
        OntModel ontModel = ModelFactory.createOntologyModel();
        ontModel.setNsPrefix("foaf", FOAF_0_1);
        ontModel.setNsPrefix("prov", PROV);
        ontModel.setNsPrefix("ore", ORE);
        ontModel.setNsPrefix("pav", PAV);
//        ontModel.getDocumentManager().loadImports(foaf.getOntModel());
        return ontModel;
    }
//    
    protected synchronized void loadFOAF() {
        if (foaf != null) {
            return;
        }

        OntModel ontModel = loadOntologyFromClasspath(FOAF_RDF, FOAF_0_1);            
        
        // properties from foaf
        foafName = ontModel.getDatatypeProperty(FOAF_0_1 + "name");
        checkNotNull(foafName);
                
        foaf = ontModel;            
    }
    

    protected synchronized void loadPAV() {
        if (pav != null) {
            return;
        }

        OntModel ontModel = loadOntologyFromClasspath(PAV_RDF, PAV);            
        
        // properties from foaf
        createdBy = ontModel.getObjectProperty(PAV + "createdBy");
        checkNotNull(createdBy);
                
        pav = ontModel;            
    }

    protected synchronized void loadPROVO() {
        if (prov != null) {
            return;
        }
        OntModel ontModel = loadOntologyFromClasspath(PROV_O_RDF, PROV_O);            
        
        checkNotNull(ontModel);
                
        prov = ontModel;            
    }


    protected synchronized void loadPROVAQ() {
        if (provaq != null) {
            return;
        }
        OntModel ontModel = loadOntologyFromClasspath(PROV_AQ_RDF, PAV);            
        
        // properties from foaf
        hasProvenance = ontModel.getObjectProperty(PROV + "has_provenance");
        checkNotNull(hasProvenance);
                
        provaq = ontModel;            
    }

    
    protected synchronized void loadORE() {
        if (ore != null) {
            return;
        }
        OntModel ontModel = loadOntologyFromClasspath("/ontologies/ore-owl.owl", "http://purl.org/wf4ever/ore-owl");
        aggregation = ontModel.getOntClass(ORE + "Aggregation");

        aggregates = ontModel.getObjectProperty(ORE + "aggregates");
        proxyFor = ontModel.getObjectProperty(ORE + "proxyFor");
        proxyIn = ontModel.getObjectProperty(ORE + "proxyIn");
        
        checkNotNull(aggregation, aggregates, proxyFor, proxyIn);
        
        
        ore = ontModel;
    }
    
    public static <T> ClosableIterable<T> iterate(ExtendedIterator<T> iterator) {
        return new ClosableIterable<T>(iterator);
    }
    
    public static class ClosableIterable<T> implements AutoCloseable, Iterable<T> {

        private ExtendedIterator<T> iterator;

        public ClosableIterable(ExtendedIterator<T> iterator) {
            this.iterator = iterator;
        }

        @Override
        public void close() {
            iterator.close();
        }

        @Override
        public ExtendedIterator<T> iterator() {
            return iterator;
        }       
    }

    public void readTo(InputStream resourceAsStream, Manifest manifest) throws IOException, RiotException {
        OntModel model = new RDFToManifest().getOntModel();
        URI base;
        try {
            base = makeBaseURI();
        } catch (URISyntaxException e) {
            throw new IllegalStateException("Can't make base URI of form app://{uuid}/", e);
        }
        try (InputStream jsonIn = getClass().getResourceAsStream("/manifest.json")) {
            model.add(jsonLdAsJenaModel(jsonIn, base));
        }
        
        Individual ro = findRO(model, base);
        for (Individual in : listObjectProperties(ro, aggregates)) {
            String uriStr = in.getURI();
            PathMetadata meta = new PathMetadata();
            if (uriStr != null) {
                meta.setUri(relativizeFromBase(uriStr, base));
            }
            Resource proxy = in.getPropertyResourceValue(proxyFor);
            if (proxy != null && proxy.getURI() != null) {
                meta.setProxy(relativizeFromBase(proxy.getURI(), base));
            }
            
            List<Agent> creators = new ArrayList<>();
            for (Individual agent : listObjectProperties(in, createdBy)) {
                Agent a = new Agent();
                if (agent.getURI() != null) {
                    a.setUri(relativizeFromBase(agent.getURI(), base));
                    
                    RDFNode name = agent.getPropertyValue(foafName);
                    if (name != null && name.isLiteral()) {
                        a.setName(name.asLiteral().getLexicalForm());
                    }
                }                
                creators.add(a);
            }
            if (! creators.isEmpty()) {
                manifest.setCreatedBy(creators);
            }
            
            manifest.getAggregates().add(meta);
        }
        
        
        
//        model.write(System.out, "TURTLE");
        
    }

    private URI relativizeFromBase(String uriStr, URI base) {
        return ROOT.resolve(base.relativize(URI.create(uriStr)));
    }

    protected static URI makeBaseURI() throws URISyntaxException {
        return new URI("app", UUID.randomUUID().toString(), "/", (String)null);
    }




    private Set<Individual> listObjectProperties(Individual in,
            ObjectProperty prop) {
        LinkedHashSet<Individual> results = new LinkedHashSet<>();
        try (ClosableIterable<RDFNode> props = iterate(in.listPropertyValues(prop))) {
            for (RDFNode node : props) {
                if (! node.isResource() || ! node.canAs(Individual.class)) {
                    continue;
                }
                results.add(node.as(Individual.class));
            }
        }
        return results;
    }

    private Individual findRO(OntModel model, URI base) {
        try (ClosableIterable<? extends OntResource> instances = iterate(aggregation.listInstances())) {
            for (OntResource o : instances) {
                System.out.println("Woo " + o);
                return o.asIndividual();
            }
        }
        // Fallback - resolve as "/"
        // TODO: Ensure it's an Aggregation?
        return model.getIndividual(base.toString());
    }

}
