/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.commons.rdf.impl.utils.graphmatching;


import org.apache.commons.rdf.impl.utils.graphmatching.collections.IntHashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.rdf.BlankNode;
import org.apache.commons.rdf.Graph;
import org.apache.commons.rdf.BlankNodeOrIri;
import org.apache.commons.rdf.RdfTerm;
import org.apache.commons.rdf.Triple;
import org.apache.commons.rdf.Graph;
import org.apache.commons.rdf.Iri;
import org.apache.commons.rdf.impl.utils.TripleImpl;
import org.apache.commons.rdf.impl.utils.graphmatching.collections.IntIterator;

/**
 *
 * @author reto
 */
public class HashMatching {

    private Map<BlankNode, BlankNode> matchings = new HashMap<BlankNode, BlankNode>();
    private Map<Set<BlankNode>, Set<BlankNode>> matchingGroups;

    /**
     * tc1 and tc2 will be modified: the triples containing no unmatched bnode
     * will be removed
     *
     * @param tc1
     * @param tc2
     * @throws GraphNotIsomorphicException
     */
    HashMatching(Graph tc1, Graph tc2) throws GraphNotIsomorphicException {
        int foundMatchings = 0;
        int foundMatchingGroups = 0;
        Map<BlankNode, Integer> bNodeHashMap = new HashMap<BlankNode, Integer>();
        while (true) {
            bNodeHashMap = matchByHashes(tc1, tc2, bNodeHashMap);
            if (bNodeHashMap == null) {
                throw new GraphNotIsomorphicException();
            }
            if (matchings.size() == foundMatchings) {
                if (!(matchingGroups.size() > foundMatchingGroups)) {
                    break;
                }
            }
            foundMatchings = matchings.size();
            foundMatchingGroups = matchingGroups.size();
        }
    }

    /**
     *
     * @return a map containing set of which each bnodes mappes one of the other set
     */
    public Map<Set<BlankNode>, Set<BlankNode>> getMatchingGroups() {
        return matchingGroups;
    }

    public Map<BlankNode, BlankNode> getMatchings() {
        return matchings;
    }

    
    private static IntHashMap<Set<BlankNode>> getHashNodes(Map<BlankNode,
            Set<Property>> bNodePropMap, Map<BlankNode, Integer> bNodeHashMap) {
        IntHashMap<Set<BlankNode>> result = new IntHashMap<Set<BlankNode>>();
        for (Map.Entry<BlankNode, Set<Property>> entry : bNodePropMap.entrySet()) {
            int hash = computeHash(entry.getValue(), bNodeHashMap);
            Set<BlankNode> bNodeSet = result.get(hash);
            if (bNodeSet == null) {
                bNodeSet = new HashSet<BlankNode>();
                result.put(hash,bNodeSet);
            }
            bNodeSet.add(entry.getKey());
        }
        return result;
    }
    /*
     * returns a Map from bnodes to hash that can be used for future
     * refinements, this could be separate for each ImmutableGraph.
     *
     * triples no longer containing an unmatched bnodes ae removed.
     *
     * Note that the matched node are not guaranteed to be equals, but only to
     * be the correct if the graphs are isomorphic.
     */
    private Map<BlankNode, Integer> matchByHashes(Graph g1, Graph g2,
            Map<BlankNode, Integer> bNodeHashMap) {
        Map<BlankNode, Set<Property>> bNodePropMap1  = getBNodePropMap(g1);
        Map<BlankNode, Set<Property>> bNodePropMap2  = getBNodePropMap(g2);
        IntHashMap<Set<BlankNode>> hashNodeMap1 = getHashNodes(bNodePropMap1, bNodeHashMap);
        IntHashMap<Set<BlankNode>> hashNodeMap2 = getHashNodes(bNodePropMap2, bNodeHashMap);
        if (!hashNodeMap1.keySet().equals(hashNodeMap2.keySet())) {
            return null;
        }

        matchingGroups = new HashMap<Set<BlankNode>, Set<BlankNode>>();
        IntIterator hashIter = hashNodeMap1.keySet().intIterator();
        while (hashIter.hasNext()) {
            int hash = hashIter.next();
            Set<BlankNode> nodes1 = hashNodeMap1.get(hash);
            Set<BlankNode> nodes2 = hashNodeMap2.get(hash);
            if (nodes1.size() != nodes2.size()) {
                return null;
            }
            if (nodes1.size() != 1) {
                matchingGroups.put(nodes1, nodes2);
                continue;
            }
            final BlankNode bNode1 = nodes1.iterator().next();
            final BlankNode bNode2 = nodes2.iterator().next();
            matchings.put(bNode1,bNode2);
            //in the graphs replace node occurences with grounded node,
            BlankNodeOrIri mappedNode = new MappedNode(bNode1, bNode2);
            replaceNode(g1,bNode1, mappedNode);
            replaceNode(g2, bNode2, mappedNode);
            //remove grounded triples
            if (!Utils.removeGrounded(g1,g2)) {
                return null;
            }
        }
        Map<BlankNode, Integer> result = new HashMap<BlankNode, Integer>();
        addInverted(result, hashNodeMap1);
        addInverted(result, hashNodeMap2);
        return result;
    }
    private static int computeHash(Set<Property> propertySet, Map<BlankNode, Integer> bNodeHashMap) {
        int result = 0;
        for (Property property : propertySet) {
            result += property.hashCode(bNodeHashMap);
        }
        return result;
    }
    private static Map<BlankNode, Set<Property>> getBNodePropMap(Graph g) {
        Set<BlankNode> bNodes = Utils.getBNodes(g);
        Map<BlankNode, Set<Property>> result = new HashMap<BlankNode, Set<Property>>();
        for (BlankNode bNode : bNodes) {
            result.put(bNode, getProperties(bNode, g));
        }
        return result;
    }
    private static Set<Property> getProperties(BlankNode bNode, Graph g) {
        Set<Property> result = new HashSet<Property>();
        Iterator<Triple> ti = g.filter(bNode, null, null);
        while (ti.hasNext()) {
            Triple triple = ti.next();
            result.add(new ForwardProperty(triple.getPredicate(), triple.getObject()));
        }
        ti = g.filter(null, null, bNode);
        while (ti.hasNext()) {
            Triple triple = ti.next();
            result.add(new BackwardProperty(triple.getSubject(), triple.getPredicate()));
        }
        return result;
    }
    private static int nodeHash(RdfTerm resource, Map<BlankNode, Integer> bNodeHashMap) {
        if (resource instanceof BlankNode) {
            Integer mapValue = bNodeHashMap.get((BlankNode)resource);
            if (mapValue == null) {
                return 0;
            } else {
                return mapValue;
            }
        } else {
            return resource.hashCode();
        }
    }
    private static void replaceNode(Graph graph, BlankNode bNode, BlankNodeOrIri replacementNode) {
        Set<Triple> triplesToRemove = new HashSet<Triple>();
        for (Triple triple : graph) {
            Triple replacementTriple = getReplacement(triple, bNode, replacementNode);
            if (replacementTriple != null) {
                triplesToRemove.add(triple);
                graph.add(replacementTriple);
            }
        }
        graph.removeAll(triplesToRemove);
    }
    private static Triple getReplacement(Triple triple, BlankNode bNode, BlankNodeOrIri replacementNode) {
        if (triple.getSubject().equals(bNode)) {
            if (triple.getObject().equals(bNode)) {
                return new TripleImpl(replacementNode, triple.getPredicate(), replacementNode);
            } else {
                return new TripleImpl(replacementNode, triple.getPredicate(), triple.getObject());
            }
        } else {
            if (triple.getObject().equals(bNode)) {
                return new TripleImpl(triple.getSubject(), triple.getPredicate(), replacementNode);
            } else {
                return null;
            }
        }
    }
    private static void addInverted(Map<BlankNode, Integer> result, IntHashMap<Set<BlankNode>> hashNodeMap) {
        for (int hash : hashNodeMap.keySet()) {
            Set<BlankNode> bNodes = hashNodeMap.get(hash);
            for (BlankNode bNode : bNodes) {
                result.put(bNode, hash);
            }
        }
    }
    
    private static class BackwardProperty implements Property {
        private BlankNodeOrIri subject;
        private Iri predicate;
    
        public BackwardProperty(BlankNodeOrIri subject, Iri predicate) {
            this.subject = subject;
            this.predicate = predicate;
        }
    
        @Override
        public int hashCode(Map<BlankNode, Integer> bNodeHashMap) {
            return  0xFF ^ predicate.hashCode() ^ nodeHash(subject, bNodeHashMap);
        }
    
    }
    private static class ForwardProperty implements Property {
        private Iri predicate;
        private RdfTerm object;
    
        public ForwardProperty(Iri predicate, RdfTerm object) {
            this.predicate = predicate;
            this.object = object;
        }
    
        @Override
        public int hashCode(Map<BlankNode, Integer> bNodeHashMap) {
            return predicate.hashCode() ^ nodeHash(object, bNodeHashMap);
        }
    }
    private static class MappedNode implements BlankNodeOrIri {
        private BlankNode bNode1, bNode2;
    
        public MappedNode(BlankNode bNode1, BlankNode bNode2) {
            this.bNode1 = bNode1;
            this.bNode2 = bNode2;
        }
        
    }
    private static interface Property {
        public int hashCode(Map<BlankNode, Integer> bNodeHashMap);
    }
}
