package it.unibz.inf.ontop.owlrefplatform.core.mappingprocessing;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableSet;
import it.unibz.inf.ontop.model.ImmutableFunctionalTerm;
import it.unibz.inf.ontop.model.ImmutableTerm;
import it.unibz.inf.ontop.pivotalrepr.ConstructionNode;
import it.unibz.inf.ontop.pivotalrepr.IntermediateQuery;
import it.unibz.inf.ontop.pivotalrepr.QueryNode;
import it.unibz.inf.ontop.pivotalrepr.UnionNode;
import it.unibz.inf.ontop.utils.ImmutableCollectors;

import java.util.Optional;
import java.util.stream.Stream;

/*
Used to retrieve the IRI involved in a same as mapping.
 */
public class SameAsIRIsExtractor   {


    private IntermediateQuery definition;
    private boolean objectProperty;

    public SameAsIRIsExtractor(IntermediateQuery definition) {

        this.definition = definition;


    }


    private ImmutableSet<ImmutableTerm> extractIRIsFromUnionNode(IntermediateQuery query, UnionNode currentNode) {

        Stream<ImmutableTerm> childrenBindings = query.getChildrenStream(currentNode)
                .flatMap(c -> extractIRIs(c));

        return childrenBindings.collect(ImmutableCollectors.toSet());


    }

    public Optional<ImmutableSet<ImmutableTerm>> getIRIs() {

        ConstructionNode rootConstructionNode = definition.getRootConstructionNode();
        if(rootConstructionNode.getSubstitution().isEmpty())
        {
            Optional<QueryNode> firstChild = definition.getFirstChild(rootConstructionNode);
            if (firstChild.isPresent()){
                QueryNode node =firstChild.get();
                if (node instanceof UnionNode){
                    //get iris in the union
                    return Optional.of(extractIRIsFromUnionNode(definition, (UnionNode) node));
                }
//                else{
//                    if (node instanceof ConstructionNode)
//                        return Optional.of(extractIRIs(node)
//                                .collect(ImmutableCollectors.toSet()));
//                }
            }

            return Optional.empty();
        }
        else{
            return Optional.of(extractIRIs(rootConstructionNode)
                    .collect(ImmutableCollectors.toSet()));
        }



    }

    /**
     * Extract the iris from the construction node, searching for its bindings and getting only the iri
     */
    private Stream<ImmutableTerm> extractIRIs(QueryNode currentNode) {

        if(currentNode instanceof ConstructionNode) {
            ConstructionNode constructionNode = (ConstructionNode) currentNode;
            ImmutableCollection<ImmutableTerm> localBindings = constructionNode.getSubstitution()
                    .getImmutableMap().values();

            // if it has two IRIs it's an object Property
            objectProperty = localBindings.stream().allMatch(v -> ((ImmutableFunctionalTerm) v).isDataFunction()) && localBindings.size() == 2;

            return localBindings.stream().map(v -> ((ImmutableFunctionalTerm) v).getTerm(0));
        }
        else {
            throw new IllegalStateException("Construction node is missing ");
        }
    }


    public boolean isObjectProperty(){
        return objectProperty;
    }




}

@@ -261,24 +261,71 @@
 utableTerm;%0A
+import it.unibz.inf.ontop.model.ValueConstant;%0A
 import it.un
@@ -696,20 +696,173 @@
 apping.%0A
- 
+Consider only simple mappings. The IRIs are retrieved from the bindings of the root construction node%0Aor from the children construction nodes of a union%0A
 */%0A
+%0A
 public c
@@ -954,17 +954,19 @@
 boolean 
-o
+isO
 bjectPro
@@ -1080,24 +1080,104 @@
 n;%0A%0A%0A    %7D%0A%0A
+    /*%0A    Get IRIs from all children (construction nodes) of the union%0A     */%0A
 %0A    private
@@ -1490,24 +1490,110 @@
 );%0A%0A%0A    %7D%0A%0A
+    /*%0A    Returns a set with the IRIs extracted from the mapping definition%0A%0A     */%0A
     public O
@@ -2193,249 +2193,8 @@
   %7D%0A
-//                else%7B%0A//                    if (node instanceof ConstructionNode)%0A//                        return Optional.of(extractIRIs(node)%0A//                                .collect(ImmutableCollectors.toSet()));%0A//                %7D%0A
     
@@ -2437,19 +2437,19 @@
 act the 
-iri
+IRI
 s from t
@@ -2480,19 +2480,23 @@
 arching 
-for
+through
  its bin
@@ -2522,19 +2522,19 @@
 nly the 
-iri
+IRI
 %0A     */
@@ -2958,17 +2958,19 @@
         
-o
+isO
 bjectPro
@@ -3185,16 +3185,124 @@
 Term(0))
+%0A                    //filter out the variables%0A                    .filter(v -%3E v instanceof ValueConstant)
 ;%0A      
@@ -3416,16 +3416,121 @@
     %7D%0A%0A%0A
+    /*%0A    Return true when the property is an object property (IRI in subject and object part)%0A     */%0A%0A
     publ
@@ -3575,17 +3575,19 @@
  return 
-o
+isO
 bjectPro

filter out variables from the results