package aalg.algebra;


/**
 * Element of multimonoid and also multigroup.
 * @author Ing. Petr Ležák
 *
 * @param <F> type of underlying field
 */
public class MultiMonoidElement<F extends IElement> implements IElement {

	private final IVector<F> parts;
	
	/**
	 * Creates monoid elements with given parts.
	 * @param parts monoid parts (vector is copied)
	 */
	public MultiMonoidElement(final IVector<F> parts) {
		this.parts = parts.copy();
	}
	
	/**
	 * Returns number of parts.
	 * @return number of parts
	 */
	public int getPartCount() {
		return parts.getSize();
	}
	
	/**
	 * Returns part at given index.
	 * @param index part index
	 * @return part
	 */
	public final F getPartAt (final int index) {
		return parts.get(index);
	}
	
	/**
	 * Returns copy of vector of internal parts.
	 * @return copy of vector of internal parts
	 */
	public IVector<F> getParts() {
		return parts.copy();
	}
	
	@Override
	public boolean equals(final Object obj) {
		if (!(obj instanceof MultiMonoidElement<?>))
			return false;
		
		final MultiMonoidElement<?> cmp = (MultiMonoidElement<?>) obj;
		
		return parts.equals(cmp.parts);
	}
	
	@Override
	public int hashCode() {
		return parts.hashCode();
	}
	
	@Override
	public String toString() {
		final StringBuilder builder = new StringBuilder();
		builder.append('[');
		
		for (int i = 0; i < parts.getSize(); i++) {
			if (i > 0)
				builder.append(", ");
			
			builder.append(parts.get(i).toString());
		}
		
		builder.append(']');
		
		return builder.toString();
	}

	/**
	 * Transforms element given field transformation.
	 * @param transformation field transformation
	 * @return transformed element
	 * @throws TransformationException thrown if transformation is not possible
	 * */
	public <T extends IElement> MultiMonoidElement<T> transform (final IFieldTransformation<F, T> transformation) throws TransformationException {
		final MultiMonoidElement<T> result = new MultiMonoidElement<T> (
			parts.transform(transformation)
		);
		
		return result;
	}
}
