// Copyright (c) 1999-2018   INRIA Nancy - Grand Est (France).
// All rights reserved.


namespace CGAL {

/*!
\ingroup PkgPeriodic4HyperbolicTriangulation2HyperbolicTranslationsClasses

The class `Hyperbolic_octagon_translation` defines an object to represent a hyperbolic
translation of the fundamental group of the Bolza surface \f$\mathcal M\f$. It accepts
one template parameter:

\tparam FT         %Field number type. Must provide exact computations with algebraic numbers,
                        notably with nested square roots. The default value for this parameter is
                        `CORE::Expr`.

A translation \f$g\f$ in \f$\mathcal G\f$ is a mapping acting on the hyperbolic plane
\f$\mathbb H^2\f$. It has the form
\f[ g(z) = \frac{ \alpha\cdot z + \beta }{ \overline{\beta}\cdot z + \overline{\alpha} }, \qquad
        \alpha,\beta \in \mathbb C, \qquad z \in \mathbb H^2, \qquad |\alpha|^2 - |\beta|^2 = 1, \f]
where \f$\overline{\alpha}\f$ and \f$\overline{\beta}\f$ are the complex conjugates of
\f$\alpha\f$ and \f$\beta\f$ respectively. In this implementation, the translation \f$g\f$
is uniquely defined by its coefficients \f$\alpha\f$ and \f$\beta\f$.

Considering the set of generators \f$\mathcal A = [a, \overline{b}, c, \overline{d}, \overline{a},
b, \overline{c}, d]\f$ as an alphabet, a translation \f$g\f$ in \f$\mathcal G\f$ can be seen as a
word on the alphabet \f$\mathcal A\f$. Each letter of this alphabet is represented as an unsigned
integer from from 0 to 7, and each word (i.e., translation) is a sequence of letters.
*/

template <typename FT = CORE::Expr>
class Hyperbolic_octagon_translation {

public:


        /// \name Types

        /*!
                %Field number type of the coefficients of \f$\alpha\f$ and \f$\beta\f$.
                 This number type must be the same as the field number type `FT` of the
                 class `Periodic_4_hyperbolic_Delaunay_triangulation_2_traits`.
                 \sa `alpha()`
                 \sa `beta()`
        */
        typedef unspecified_type                         FT;

        /*!
                Represents a single letter of the alphabet \f$\mathcal A\f$.
                By extension, represents a generator of the group \f$\mathcal G\f$.
        */
        typedef unsigned short int                         Word_letter;

        /*!
                Represents a word on the alphabet \f$\mathcal A\f$. By extension, represents
                a hyperbolic translation in the group \f$\mathcal A\f$.
        */
        typedef std::vector<Word_letter>         Word;

        /*!
                Enumeration type for the alphabet \f$\mathcal A\f$. This enumeration can
                be used to recover the generators of the group \f$\mathcal G\f$.
                \sa `generator()`
        */
        enum Generator: Word_letter {
                /*! translation \f$a\f$ */
                A                 = 0,
                /*! translation \f$\overline{b}\f$ */
                B_BAR         = 1,
                /*! translation \f$c\f$ */
                C                 = 2,
                /*! translation \f$\overline{d}\f$ */
                D_BAR         = 3,
                /*! translation \f$\overline{a}\f$ */
                A_BAR         = 4,
                /*! translation \f$b\f$ */
                B                  = 5,
                /*! translation \f$\overline{c}\f$ */
                C_BAR         = 6,
                /*! translation \f$d\f$ */
                D                 = 7
        };

        /// \name Creation

        /// Default constructor. Creates the identity translation of the group \f$\mathcal G\f$.
        Hyperbolic_octagon_translation();

        /// Creates the translation described by the word `w`.
        Hyperbolic_octagon_translation(Word w);

        /// Creates the translation described by the one-letter word `l`.
        Hyperbolic_octagon_translation(Word_letter l);

        /// Creates the translation described by the two-letter word `lm`.
        Hyperbolic_octagon_translation(Word_letter l, Word_letter m);

        /// Creates the translation described by the three-letter word `lmn`.
        Hyperbolic_octagon_translation(Word_letter l, Word_letter m, Word_letter n);

        /// Creates the translation described by the four-letter word `lmno`.
        Hyperbolic_octagon_translation(Word_letter l, Word_letter m, Word_letter n, Word_letter o);


        /// \name Operations

        /// Multiplication operator; composes the current translation with `other`.
        Hyperbolic_octagon_translation operator*(const Hyperbolic_octagon_translation& other) const;

        ///        Difference operator; the difference of two translations \f$v\f$ and \f$w\f$ is defined as \f$v * w^{-1}\f$.
          Hyperbolic_octagon_translation operator-(const Hyperbolic_octagon_translation& other) const;

          /// Assignment operator; modifying the translation after the assignment leaves `other` unaffected.
        Hyperbolic_octagon_translation& operator=(const Hyperbolic_octagon_translation& other);

        /// Equality operator.
        bool operator==(const Hyperbolic_octagon_translation<FT>& other) const;

        /// Inequality operator.
        bool operator!=(const Hyperbolic_octagon_translation<FT>& other) const;

        /*!
                Comparison operator.
                 Each translation \f$g\f$ of \f$\mathcal G\f$, when applied to the octagon \f$\mathcal D_O\f$,
                 produces a copy of \f$\mathcal D_O\f$ labeled by the translation \f$g\f$. The copies of
                 \f$\mathcal D_O\f$ incident to \f$\mathcal D_O\f$ are naturally ordered counterclockwise around
                 \f$\mathcal D_O\f$. The comparison operator compares two translations based on the ordering
                 of the copies of \f$\mathcal D_O\f$ that they produce. For more details, see Section
                 \ref P4HT2_representation of the User manual.
        */
        bool operator<(const Hyperbolic_octagon_translation<FT>& other) const;

        /// Returns the inverse of the current translation.
        Hyperbolic_octagon_translation inverse() const;


        /// \name Access Functions

        /// Returns the coefficient \f$\alpha\f$ of the translation. The first element of the returned `pair`
        /// contains the real part of \f$\alpha\f$. The second element contains its imaginary part.
        std::pair<FT,FT> alpha() const;

        /// Returns the coefficient \f$\beta\f$ of the translation. The first element of the returned `pair`
        /// contains the real part of \f$\beta\f$. The second element contains its imaginary part.
        std::pair<FT,FT> beta() const;

        /// Returns `true` if the current translation represents the identity element of the group \f$\mathcal G\f$.
        bool is_identity();


        /// \name Static Access Functions

        /*!
                Return the generator `wl` of the group \f$\mathcal G\f$.
                Note that `wl` can be an element of the enumeration set Generator. The calls
                `generator(0)` and `generator(A)` will both return the translation \f$a\f$.
        */
        static Self generator(const Word_letter wl) {
                return Self(wl);
        }

        /*!
                Returns the set of generators of \f$\mathcal G\f$ and their inverses in a `std::vector`.
                The generators are given in the order:
                \f$ [a, \overline{b}, c, \overline{d}, \overline{a}, b, \overline{c}, d].\f$
         */
        static void generators(std::vector< Hyperbolic_octagon_translation<FT> >& gens);


        /// \name Utility Functions
        /// @{

                /*!
                        Returns a string representation of the translation, containing its `Word_letter`s.
                        This function is given as utility for printing/debugging purposes. For example,
                        for the translation \f$abcd\f$, this function returns `0527`, and for the identity
                        it returns `_`.
                */
                std::string to_string() const;
        /// @}
};

} // namespace CGAL
