package ch.hsr.servicecutter.scorer.criterionScorer;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import ch.hsr.servicecutter.model.solver.EntityPair;
import ch.hsr.servicecutter.model.usersystem.CouplingInstance;
import ch.hsr.servicecutter.model.usersystem.Nanoentity;

public class RelatedGroupCriteriaScorer implements CriterionScorer {

	private double penalty;
	private double premium;
	private Iterable<Nanoentity> allNanoentities;
	private boolean penalityToOtherGroups;
	private boolean penalityToAll;

	public RelatedGroupCriteriaScorer(final double penalty, final double premium, final Iterable<Nanoentity> iterable, final boolean penalityToOtherGroups,
			final boolean penalityToAll) {
		this.penalty = penalty;
		this.premium = premium;
		this.allNanoentities = iterable;
		this.penalityToOtherGroups = penalityToOtherGroups;
		this.penalityToAll = penalityToAll;
	}

	// constructor to only set premium within scores
	public RelatedGroupCriteriaScorer(final double premium) {
		this(0d, premium, Collections.emptyList(), false, false);
	}

	// constructor to only set penaltiy to other groups
	public RelatedGroupCriteriaScorer(final double premium, final double penalty) {
		this(penalty, premium, Collections.emptyList(), true, false);
	}

	// constructor to only set penaltiy to all nanoentities not in group
	public RelatedGroupCriteriaScorer(final double premium, final double penalty, final Iterable<Nanoentity> allEntities) {
		this(penalty, premium, allEntities, false, true);
	}

	@Override
	public Map<EntityPair, Double> getScores(final Set<CouplingInstance> instances) {
		Map<EntityPair, Double> result = new HashMap<>();
		for (CouplingInstance instance : instances) {
			// add Premium to nanoentities in same group
			if (premium != 0d) {
				for (int i = 0; i < instance.getAllNanoentities().size() - 1; i++) {
					for (int j = i + 1; j < instance.getAllNanoentities().size(); j++) {
						result.put(new EntityPair(instance.getAllNanoentities().get(i), instance.getAllNanoentities().get(j)), premium);
					}
				}
			}
			if (penalty != 0 && penalityToAll) {
				setPenaltyToOtherFields(result, instance, allNanoentities);
			}

			if (penalty != 0 && penalityToOtherGroups) {
				List<Nanoentity> allNanoentitiesInInstances = instances.stream().flatMap(i -> i.getAllNanoentities().stream()).collect(Collectors.toList());
				setPenaltyToOtherFields(result, instance, allNanoentitiesInInstances);
			}
		}
		return result;
	}

	private void setPenaltyToOtherFields(final Map<EntityPair, Double> result, final CouplingInstance instance, final Iterable<Nanoentity> otherNanoentities) {
		for (Nanoentity groupEntity : instance.getAllNanoentities()) {
			for (Nanoentity otherEntity : otherNanoentities) {
				if (!instance.getAllNanoentities().contains(otherEntity)) {
					result.put(new EntityPair(groupEntity, otherEntity), penalty);
				}
			}
		}
	}

}

@@ -562,33 +562,32 @@
 te boolean penal
-i
 tyToOtherGroups;
@@ -605,25 +605,24 @@
 oolean penal
-i
 tyToAll;%0A%0A%09p
@@ -750,25 +750,24 @@
 oolean penal
-i
 tyToOtherGro
@@ -789,25 +789,24 @@
 oolean penal
-i
 tyToAll) %7B%0A%09
@@ -899,25 +899,24 @@
 %09%09this.penal
-i
 tyToOtherGro
@@ -922,25 +922,24 @@
 oups = penal
-i
 tyToOtherGro
@@ -951,25 +951,24 @@
 %09%09this.penal
-i
 tyToAll = pe
@@ -966,25 +966,24 @@
 oAll = penal
-i
 tyToAll;%0A%09%7D%0A
@@ -1167,37 +1167,32 @@
  constructor to 
-only 
 set penaltiy to 
@@ -1181,25 +1181,24 @@
 o set penalt
-i
 y to other g
@@ -1244,38 +1244,38 @@
 r(final double p
-remium
+enalty
 , final double p
@@ -1274,22 +1274,22 @@
 double p
-enalty
+remium
 ) %7B%0A%09%09th
@@ -1367,29 +1367,24 @@
 structor to 
-only 
 set penaltiy
@@ -1381,17 +1381,16 @@
 t penalt
-i
 y to all
@@ -1457,38 +1457,38 @@
 r(final double p
-remium
+enalty
 , final double p
@@ -1479,38 +1479,38 @@
 , final double p
-enalty
+remium
 , final Iterable
@@ -2167,25 +2167,24 @@
 = 0 && penal
-i
 tyToAll) %7B%0A%09
@@ -2280,17 +2280,16 @@
 && penal
-i
 tyToOthe

fix wrong params