package aalg.algebra;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;

/**
 * Algebraic structure is a set containing elements.
 * @author Ing. Petr Ležák
 *
 * @param <T> type of elements
 */
public interface IAlgebraicStructure<T extends IElement> {
	/**
	 * Reads element from given stream.
	 * @param stream input stream
	 * @return read element
	 * @throws IOException in case of IO error
	 */
	public T readElement (final InputStream stream) throws IOException;
	
	/**
	 * Writes element into stream.
	 * @param element element to write
	 * @param stream output stream
	 * @throws IOException in case of IO error
	 */
	public void writeElement (final T element, final OutputStream stream) throws IOException;
	
	/**
	 * Returns set of elements. This set may be finite or infinite.
	 * In case of infinite set it is not necessary that iterating through it returns
	 * all elements because it may also be uncountable.
	 * @return Iterable that iterates through structure elements
	 */
	public Iterable<T> getElements();
	
	/**
	 * Checks if this algebraic structure contains given element.
	 * @param element element to check
	 * @return true if algebraic structure contains element, false if not
	 */
	public boolean containsElement (final T element);
	
	/**
	 * Returns order of set with elements.
	 * @return number of elements or null in case of infinite set
	 */
	public BigInteger getOrder();
	
	/**
	 * Returns index of element in range 0 <= index < order.
	 * If set of elements is infinite returns null
	 * @param element element
	 * @return element index
	 */
	public BigInteger getElementIndex(final T element);

	/**
	 * Parses given string to element.
	 * @param string string representation
	 * @return element
	 */
	public T elementFromString(final String string);
}
