package it.unibz.inf.ontop.spec.mapping;


import com.google.common.collect.ImmutableSet;
import it.unibz.inf.ontop.spec.ontology.DataPropertyExpression;
import it.unibz.inf.ontop.spec.ontology.OClass;
import it.unibz.inf.ontop.spec.ontology.ObjectPropertyExpression;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * Class for TMapping Optimization. The Mappings for the classes and properties in the configuration are assumed to "exact".
 * Therefore, the TMappings for those predicates are not needed to be generated by
 * {@see it.unibz.inf.obda.owlrefplatform.core.mappingprocessing.TMappingSaturatorImpl}
 */
public class TMappingExclusionConfig {

    private final ImmutableSet<String> classes;

    private final ImmutableSet<String> properties;

    public TMappingExclusionConfig(ImmutableSet<String> classes, ImmutableSet<String> properties){
        this.classes = classes;
        this.properties = properties;
    }

    public boolean contains(OClass cls){
        return classes.contains(cls.getIRI().getIRIString());
    }

    public boolean contains(ObjectPropertyExpression propertyExpression){
        return !propertyExpression.isInverse() && properties.contains(propertyExpression.getIRI().getIRIString());
    }

    public boolean contains(DataPropertyExpression propertyExpression){
        return  properties.contains(propertyExpression.getIRI().getIRIString());
    }

    /**
     * @return a default empty configuration
     */
    public static TMappingExclusionConfig empty(){
        return new TMappingExclusionConfig(ImmutableSet.of(), ImmutableSet.of());
    }

    public static TMappingExclusionConfig parseFile(String fileName) throws IOException {
        Set<String> classes = new HashSet<>();
        Set<String> properties = new HashSet<>();

        try(BufferedReader in = new BufferedReader(new FileReader(fileName))) {
            String s;
            while ((s = in.readLine()) != null) {
                s = s.trim();
                // empty line or comments
                if (s.isEmpty() || s.startsWith("#")) {
                    continue;
                }
                String[] s2 = s.split(" ");

                if (s2.length != 2) {
                    throw new IllegalArgumentException("cannot parse line (too many columns): " + s);
                }

                try {
                    int arity = Integer.parseInt(s2[1]);
                    switch (arity) {
                        case 1:
                            classes.add(s2[0]);
                            break;
                        case 2:
                            properties.add(s2[0]);
                            break;
                        default:
                            throw new IllegalArgumentException("cannot parse line (wrong arity): " + s);
                    }
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("cannot parse line (wrong arity): " + s);
                }
            }

        }
        return new TMappingExclusionConfig(ImmutableSet.copyOf(classes), ImmutableSet.copyOf(properties));
    }
}
