package in.cdac.medinfo.csnotk.csnolib.ecl.constraint;

import org.snomed.langauges.ecl.domain.Pair;
import org.snomed.langauges.ecl.domain.expressionconstraint.CompoundExpressionConstraint;
import org.snomed.langauges.ecl.domain.expressionconstraint.SubExpressionConstraint;

import java.util.List;
import java.util.stream.Collectors;
//Changes
import in.cdac.medinfo.csnotk.csnolib.model.Concept;
import java.util.Set;
import com.google.common.collect.Sets;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.stream.Collectors.toSet;

public class SCompoundExpressionConstraint extends CompoundExpressionConstraint implements SConstraint {

    @Override
    public Set<Concept> addQuery() {
        int firstConceptCounter = 0;
        Set<Concept> finalSctIds = null;
        if (getConjunctionExpressionConstraints() != null) {
            for (SSubExpressionConstraint conjunctionExpressionConstraint : getSConjunctionExpressionConstraints()) {
                if( firstConceptCounter++ == 0 )
                    finalSctIds = conjunctionExpressionConstraint.addQuery();
                else
                    finalSctIds = Sets.intersection( finalSctIds, conjunctionExpressionConstraint.addQuery());
            }
        } else if (getDisjunctionExpressionConstraints() != null) {
            for (SSubExpressionConstraint disjunctionExpressionConstraint : getSDisjunctionExpressionConstraints()) {
                if( firstConceptCounter++ == 0 )
                    finalSctIds = disjunctionExpressionConstraint.addQuery();
                else
                    finalSctIds = Sets.union( finalSctIds, disjunctionExpressionConstraint.addQuery());
            }
        } else if (getExclusionExpressionConstraints() != null) {
            Pair<SubExpressionConstraint> pair = getExclusionExpressionConstraints();
            finalSctIds = Sets.difference( ((SSubExpressionConstraint)pair.getFirst()).addQuery(), ((SSubExpressionConstraint)pair.getSecond()).addQuery());
        }
        return finalSctIds;
    }

    public List<SSubExpressionConstraint> getSConjunctionExpressionConstraints() {
        if (getConjunctionExpressionConstraints() == null) {
            return null;
        }
        return getConjunctionExpressionConstraints().stream().map(constraint -> (SSubExpressionConstraint) constraint).collect(Collectors.toList());
    }

    public List<SSubExpressionConstraint> getSDisjunctionExpressionConstraints() {
        if (getDisjunctionExpressionConstraints() == null) {
            return null;
        }
        return getDisjunctionExpressionConstraints().stream().map(constraint -> (SSubExpressionConstraint) constraint).collect(Collectors.toList());
    }

    @Override
    public Set<String> getConceptIds() {
        Set<String> conceptIds = newHashSet();
        if (conjunctionExpressionConstraints != null) {
            conceptIds.addAll(getConceptIds(conjunctionExpressionConstraints));
        } else if (disjunctionExpressionConstraints != null) {
            conceptIds.addAll(getConceptIds(disjunctionExpressionConstraints));
        } else {
            conceptIds.addAll(((SSubExpressionConstraint) exclusionExpressionConstraints.getFirst()).getConceptIds());
            conceptIds.addAll(((SSubExpressionConstraint) exclusionExpressionConstraints.getSecond()).getConceptIds());
        }
        return conceptIds;
    }

    private Set<String> getConceptIds(List<SubExpressionConstraint> subExpressionConstraints) {
        return subExpressionConstraints.stream()
                .map(SSubExpressionConstraint.class::cast)
                .map(SSubExpressionConstraint::getConceptIds)
                .flatMap(Set::stream)
                .collect(toSet());
    }

}
