package at.ac.tuwien.kr.alpha.common.rule;

import java.util.ArrayList;
import java.util.List;

import at.ac.tuwien.kr.alpha.Util;
import at.ac.tuwien.kr.alpha.common.atoms.Atom;
import at.ac.tuwien.kr.alpha.common.atoms.Literal;
import at.ac.tuwien.kr.alpha.common.rule.head.DisjunctiveHead;
import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead;

/**
 * A rule that has a normal head, i.e. just one head atom, no disjunction or choice heads allowed Currently, any constructs such as aggregates, intervals, etc.
 * in the rule body are allowed.
 * 
 * Copyright (c) 2019, the Alpha Team.
 */
public class NormalRule extends AbstractRule<NormalHead> {

	public NormalRule(NormalHead head, List<Literal> body) {
		super(head, body);
	}

	public static NormalRule fromBasicRule(BasicRule rule) {
		Atom headAtom = null;
		if (!rule.isConstraint()) {
			if (!rule.getHead().isNormal()) {
				throw Util.oops("Trying to construct a NormalRule from rule with non-normal head!");
			}
			if (rule.getHead() instanceof DisjunctiveHead) {
				headAtom = ((DisjunctiveHead) rule.getHead()).disjunctiveAtoms.get(0);
			} else if (rule.getHead() instanceof NormalHead) {
				headAtom = ((NormalHead) rule.getHead()).getAtom();
			} else {
				throw Util.oops("Trying to construct a rule with unsuppported head type: " + rule.getHead().getClass().getSimpleName());
			}
		}
		return new NormalRule(headAtom != null ? new NormalHead(headAtom) : null, new ArrayList<>(rule.getBody()));
	}

	public static Builder builder() {
		return new Builder();
	}

	public boolean isGround() {
		if (!isConstraint() && !this.getHead().isGround()) {
			return false;
		}
		for (Literal bodyElement : this.getBody()) {
			if (!bodyElement.isGround()) {
				return false;
			}
		}
		return true;
	}

	public Atom getHeadAtom() {
		return this.isConstraint() ? null : this.getHead().getAtom();
	}

	public static class Builder {

		private Atom headAtom;
		private List<Literal> body = new ArrayList<>();

		public NormalRule build() {
			return new NormalRule(new NormalHead(headAtom), body);
		}

		public Builder withHead(Atom h) {
			this.headAtom = h;
			return this;
		}

		public Builder withBodyAtom(Atom ba) {
			this.body.add(ba.toLiteral());
			return this;
		}

		public Builder withNegativeBodyAtom(Atom ba) {
			this.body.add(ba.toLiteral(false));
			return this;
		}
	}

}

@@ -1476,71 +1476,8 @@
 %09%7D%0A%0A
-%09public static Builder builder() %7B%0A%09%09return new Builder();%0A%09%7D%0A%0A
 %09pub
@@ -1805,494 +1805,6 @@
 %09%7D%0A%0A
-%09public static class Builder %7B%0A%0A%09%09private Atom headAtom;%0A%09%09private List%3CLiteral%3E body = new ArrayList%3C%3E();%0A%0A%09%09public NormalRule build() %7B%0A%09%09%09return new NormalRule(new NormalHead(headAtom), body);%0A%09%09%7D%0A%0A%09%09public Builder withHead(Atom h) %7B%0A%09%09%09this.headAtom = h;%0A%09%09%09return this;%0A%09%09%7D%0A%0A%09%09public Builder withBodyAtom(Atom ba) %7B%0A%09%09%09this.body.add(ba.toLiteral());%0A%09%09%09return this;%0A%09%09%7D%0A%0A%09%09public Builder withNegativeBodyAtom(Atom ba) %7B%0A%09%09%09this.body.add(ba.toLiteral(false));%0A%09%09%09return this;%0A%09%09%7D%0A%09%7D%0A%0A
 %7D%0A

remove unused builder for NormalRule