/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.mathematical.groups;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.mathematical.groups.impl.Exponent;

/**
 * Representation of a mathematical group element.
 * <p>
 * GroupElements are immutable.
 * 
 * @param <T>
 *            the GroupElement value type.
 */
public interface GroupElement<T> {

    /**
     * Returns a {@code GroupElement} whose value is {@code (this * element)}.
     * 
     * @param element
     *            The element to be multiplied by this (cannot be null).
     * @return (this * element).
     * @throws GeneralCryptoLibException
     *             if {@code element} is invalid.
     */
    GroupElement<T> multiply(GroupElement<T> element)
            throws GeneralCryptoLibException;

    /**
     * Returns a {@code GroupElement} whose value is (this<sup>exponent</sup>).
     * 
     * @param exponent
     *            the exponent to which this {@code GroupElement} is to be
     *            raised.
     * @return (this<sup>exponent</sup>).
     * @throws GeneralCryptoLibException
     *             if {@code exponent} is invalid.
     */
    GroupElement<T> exponentiate(Exponent exponent)
            throws GeneralCryptoLibException;

    /**
     * Inverts the element.
     * 
     * @return the inverse of this element
     */
    GroupElement<T> invert();

    /**
     * Returns the element value.
     * 
     * @return element value.
     */
    T getValue();
}
