// TortoiseSVN - a Windows shell extension for easy version control

// Copyright (C) 2003-2008, 2012, 2019, 2021 - TortoiseSVN

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
#pragma once

// include base classes

#include "RevisionGraphOptions.h"
#include "RevisionGraphOptionsImpl.h"

/**
* Extends the base interface with a method that has full
* modifying access to a given visible graph.
*/

class IModificationOption : public IOrderedTraversalOption
{
public:
    /// If true, the option shall be applied with all other
    /// clyclic options more than once until the graph is stable.

    virtual bool IsCyclic() const = 0;

    /// Apply / execute the filter.

    virtual void Apply(CVisibleGraph* graph, CVisibleGraphNode* node) = 0;

    /// will be called after each tree traversal.
    /// Use this to modify the tree is a way that interferes
    /// with the standard traversal, for instance.

    virtual void PostFilter(CVisibleGraph* graph) = 0;
};

/**
 * Standard implementation of IModificationOption.
 */

template <class Base, int Prio, UINT ID, bool CopyiesFirst, bool RootFirst, bool Cyclic>
class CModificationOptionImpl
    : public COrderedTraversalOptionImpl<Base, Prio, ID, CopyiesFirst, RootFirst>
{
protected:
    /// for simplied construction by the _derived_ class

    using Inherited = typename CModificationOptionImpl<Base, Prio, ID, CopyiesFirst, RootFirst, Cyclic>;

public:
    /// construction / destruction

    CModificationOptionImpl(CRevisionGraphOptionList& list)
        : COrderedTraversalOptionImpl<Base, Prio, ID, CopyiesFirst, RootFirst>(list)
    {
    }

    /// implement IModificationOption

    virtual bool IsCyclic() const override { return Cyclic; }
    virtual void PostFilter(CVisibleGraph*) override{};
};

/**
* Filtered sub-set of \ref CAllRevisionGraphOptions.
* It applies all options in the order defined by their \ref priority.
* The option instances may transform the graph any way they consider fit.
*
* Contains only \ref IModificationOption instances.
*/

class CModificationOptions : public CRevisionGraphOptionList
{
private:
    std::vector<IModificationOption*> options;

    /// apply a filter using different traversal orders

    static void TraverseFromRootCopiesFirst(IModificationOption* option, CVisibleGraph* graph, CVisibleGraphNode* node);
    static void TraverseToRootCopiesFirst(IModificationOption* option, CVisibleGraph* graph, CVisibleGraphNode* node);
    static void TraverseFromRootCopiesLast(IModificationOption* option, CVisibleGraph* graph, CVisibleGraphNode* node);
    static void TraverseToRootCopiesLast(IModificationOption* option, CVisibleGraph* graph, CVisibleGraphNode* node);
    void        InternalApply(CVisibleGraph* graph, bool cyclicFilters);

public:
    /// construction / destruction

    CModificationOptions(const std::vector<IModificationOption*>& options);
    ~CModificationOptions() override {}

    /// apply all filters

    void Apply(CVisibleGraph* graph);
};
