/*********************************************************************
 *  Author  : Tino Weinkauf and Wiebke Koepp
 *  Init    : Friday, March 23, 2018 - 15:58:29
 *
 *  Project : KTH Inviwo Modules
 *
 *  License : Follows the Inviwo BSD license model
 *********************************************************************
 */

#pragma once

#include "treeordercomputation.h"
#include "constraint.h"
#include <queue>

using namespace constraint;

class TemporalTreeOrderComputationHeuristic
    : public TemporalTreeOrderOptimization {
    // Friends
    // Types
public:
    // Construction / Deconstruction
public:
    TemporalTreeOrderComputationHeuristic();
    virtual ~TemporalTreeOrderComputationHeuristic() = default;

    // Methods
public:
    static void findConflictingLeaves(std::shared_ptr<const TemporalTree>& tree,
                                      const Constraint& constraint,
                                      const TemporalTree::TTreeOrder& order, size_t& minOrder,
                                      size_t& maxOrder, TemporalTree::TTreeOrder& conflictingLeaves,
                                      TemporalTree::TTreeOrder& nonConflictingAndConstraintLeaves);

    static void buildNewOrder(TemporalTree::TTreeOrder& newOrder,
                              const TemporalTree::TTreeOrder& order, const size_t numConflictBefore,
                              const TemporalTree::TTreeOrder& conflictingLeaves,
                              const TemporalTree::TTreeOrder& nonConflictingAndConstraintLeaves,
                              const size_t minOrder, const size_t maxOrder);

public:
    bool resolveConstraint(std::shared_ptr<const TemporalTree> tree, Constraint& constraint);

    /// Initial order
    void initializeResources();

    void restart() override;

    /// Is the optimization converged
    bool isConverged() override;

    /// Do a single optimization step
    void singleStep() override;

    /// Run until convergence criterion is reached
    void runUntilConvergence() override;

    void prepareNextStep();

    void logStep() override;

    void initializeLog() override;

    void logProperties() override;

    /// Our main computation function (Does nothing)
    virtual void process() override;

    // Ports
public:
    // Properties
public:
    /// Initial ordering of all unfulfilled constraints
    int propInitialConstraintOrder;

    // Attributes
public:
    /// Order for the current order
    TemporalTree::TTreeOrderMap currentOrderMap;

    /// Sorted constraints that we operate on
    std::vector<size_t> constraintOrder;

    /// Queue of unfulfilled constraints
    std::queue<size_t> constraintsQueue;
};
