/*
 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
 *
 * This file is part of the KGantt library.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#ifndef KGANTTCONSTRAINT_H
#define KGANTTCONSTRAINT_H

#include <QMap>
#include <QModelIndex>
#include <QObject>
#include <QSharedDataPointer>
#include <QVariant>

#include "kganttglobal.h"
#ifndef QT_NO_DEBUG_STREAM
#include <QDebug>
#endif

namespace KGantt
{

/*!\class KGantt::Constraint
 *\ingroup KGantt
 * \brief A class used to represent a dependency.
 *
 * Instances of this class represent a dependency between the
 * data items pointed to by a start-QModelIndex and an
 * end-QModelIndex.
 */
class KGANTT_EXPORT Constraint
{
    class Private;

public:
    /*!\enum KGantt::Constraint::Type
     * This enum is unused for now.
     */
    enum Type {
        TypeSoft = 0,
        TypeHard = 1
    };
    enum RelationType {
        FinishStart = 0,
        FinishFinish = 1,
        StartStart = 2,
        StartFinish = 3
    };

    /*!\enum KGantt::Constraint::ConstraintDataRole
     * Data roles used when specifying the pen to draw constraints with.
     * \sa setData
     */
    enum ConstraintDataRole {
        ValidConstraintPen = Qt::UserRole,
        InvalidConstraintPen
    };

    typedef QMap<int, QVariant> DataMap;

    /*! Default constructor, created an invalid constraint. */
    Constraint();

    /*! Constructor. Creates a dependency for \a idx2 on \a idx1.
     * \param type controls if the constraint is a soft one that
     * is allowed to be broken (ie, go backwards in time) or a hard
     * constraint that will not allow the user to move an item so
     * that the constraint would have to go backwards. The default is
     * TypeSoft.
     *
     * Actually enforcing hard constraints is the responsibility of
     * the AbstractGrid subclass used in the view.
     *
     * \param relationType defines how the tasks depends on each other.
     * relationType can be FinishStart (default), FinishFinish, StartStart or StartFinish.
     */
    Constraint(const QModelIndex &idx1, const QModelIndex &idx2, Type type = TypeSoft, RelationType relType = FinishStart, const DataMap &datamap = DataMap());

    /*! Copy-Constructor. */
    Constraint(const Constraint &other);

    /*! Destructor */
    ~Constraint();

    /*! This is unused for now. */
    Type type() const;

    /*! This is unused for now. */
    RelationType relationType() const;

    /*! \returns The dependency index */
    QModelIndex startIndex() const;

    /*! \returns The constrained index */
    QModelIndex endIndex() const;

    /*! Set data on this index for the specified role.
     * \param role The role to set the data for.
     * \param value The data to set on the index.
     * \sa ConstraintDataRole
     */
    void setData(int role, const QVariant &value);

    /*! \returns The data associated with this index for the specified role.
     * \param role The role to fetch the data for.
     * \sa ConstraintDataRole
     */
    QVariant data(int role) const;

    /*! Set data on this constraint to the keys/values in \a datamap.
     * Clears any existing data from the constraint.
     */
    void setDataMap(const QMap<int, QVariant> &datamap);

    /*! \returns all the data set on this constraint. \see setDataMap
     */
    QMap<int, QVariant> dataMap() const;

    bool compareIndexes(const Constraint &other) const;

    /*! Assignment operator. */
    Constraint &operator=(const Constraint &other);

    /*! Compare two Constraint objects. Two Constraints are equal
     * if the have the same start and end indexes
     */
    bool operator==(const Constraint &other) const;

    inline bool operator!=(const Constraint &other) const
    {
        return !operator==(other);
    }

    /*!\internal*/
    uint hash() const;
#ifndef QT_NO_DEBUG_STREAM
    QDebug debug(QDebug dbg) const;
#endif

private:
    QSharedDataPointer<Private> d;
};

inline uint qHash(const Constraint &c)
{
    return c.hash();
}
}

#ifndef QT_NO_DEBUG_STREAM
QDebug KGANTT_EXPORT operator<<(QDebug dbg, const KGantt::Constraint &c);
#endif /* QT_NO_DEBUG_STREAM */

#endif /* KGANTTCONSTRAINT_H */
