/**
 * @file vertex.hpp
 *
 * CopyRight F. J. Madrid-Cuevas <fjmadrid@uco.es>
 *
 * Sólo se permite el uso de este código en la docencia de las asignaturas sobre
 * Estructuras de Datos de la Universidad de Córdoba.
 *
 * Está prohibido su uso para cualquier otro objetivo.
 */
#pragma once
#include <memory>

template <class T>
class WGraph;
template <class T>
class const_Vertex;
template <class T>
class Edge;
template <class T>
class const_Edge;
template <class T>
class VertexIterator;
template <class T>
class const_VertexIterator;

/**
 * @brief Class to model the Vertex of a WGraph ADT.
 *
 * @tparam T is the vertex's data item type.
 *
 * It is assumed that T type defines a type T::key_t and
 * a method 'T::key_t T::key() const'
 *
 * @ingroup graph
 */
template <class T>
class Vertex
{
public:
    /** @name Makers*/
    /** @{*/

    /**
     * @brief Makes a default vertex.
     * @post !is_valid()
     */
    Vertex();
    /** @}*/

    /** @name Observers*/
    /**@{*/

    /**
     * @brief Is this vertex valid?
     * @return true if this vertex belongs to a graph.
     */
    bool is_valid() const;

    /**
     * @brief Get saved data item.
     * @return the saved data item.
     * @pre is_valid()
     */
    const T &item() const;

    /**
     * @brief get the label of the vertex.
     * @return the vertex's label.
     * @pre is_valid()
     * @post no other vertex in the graph has this label.
     */
    size_t label() const;

    /**
     * @brief Is the vertex visited?
     * @return true if the vertex was visited.
     * @pre is_valid()
     */
    bool is_visited() const;

    /**
     * @brief Compare this vertex with other vertex.
     *
     * @param other vertex to compare with.
     * @return true if this vertex and other are the same vertex of the same graph.
     */
    bool operator==(const Vertex<T> &other) const;

    /**@}*/

    /** @name Modifiers*/
    /** @{*/

    /**@brief Set data saved in the vertex.
     * @param[in] item is the data to save in.
     * @pre is_valid()
     * @post item()==item
     */
    void set_item(T const &new_item);

    /**
     *  @brief Set the flag visited
     *  @param new_state is the state to set.
     *  @pre is_valid()
     *  @post is_visited()=new_state
     */
    void set_visited(bool new_state);
    /** @} */

protected:
    friend class WGraph<T>;
    friend class VertexIterator<T>;
    friend class const_VertexIterator<T>;

    /**
     * @brief Makes a new vertex.
     * @param label is the vertex label.
     * @param graph is the graph this vertex belongs to.
     * @post !is_valid()|| graph->item(label) == item()
     */
    Vertex(size_t label, WGraph<T> *graph);

    size_t label_;     /**< the vertex label (unique in the graph)*/
    WGraph<T> *graph_; /**< the graph this vertex belongs to.*/
};

#include <vertex_imp.hpp>
