////////////////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2026 OVITO GmbH, Germany
//
//  This file is part of OVITO (Open Visualization Tool).
//
//  OVITO is free software; you can redistribute it and/or modify it either under the
//  terms of the GNU General Public License version 3 as published by the Free Software
//  Foundation (the "GPL") or, at your option, under the terms of the MIT License.
//  If you do not alter this notice, a recipient may use your version of this
//  file under either the GPL or the MIT License.
//
//  You should have received a copy of the GPL along with this program in a
//  file LICENSE.GPL.txt.  You should have received a copy of the MIT License along
//  with this program in a file LICENSE.MIT.txt
//
//  This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
//  either express or implied. See the GPL or the MIT License for the specific language
//  governing rights and limitations.
//
////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <ovito/core/Core.h>
#include <ovito/core/dataset/pipeline/PipelineNode.h>

namespace Ovito {

/**
 * \brief General base class for pipeline data source implementations.
 */
class OVITO_CORE_EXPORT BasePipelineSource : public PipelineNode
{
    OVITO_CLASS(BasePipelineSource)

public:

    /// Returns the list of data objects that are managed by this data source.
    /// The returned data objects will be displayed as sub-objects of the data source in the pipeline editor.
    virtual const DataCollection* getSourceDataCollection() const override { return dataCollection(); }

    /// Replaces all references to the given visual element in the pipeline with new compatible objects.
    virtual void replaceVisualElement(DataVis* visElement, const std::function<OORef<DataVis>(const QString&)>& getReplacement) override;

protected:

    /// Is called when a RefTarget referenced by this object generated an event.
    virtual bool referenceEvent(RefTarget* source, const ReferenceEvent& event) override;

    /// Post-processes the DataCollection generated by the data source and updates the internal master data collection.
    void postprocessDataCollection(Future<PipelineFlowState>& stateFuture, const PipelineEvaluationRequest& request);

    /// Gets called by the PipelineCache whenever it returns a pipeline state from the cache.
    virtual PipelineEvaluationResult postprocessCachedState(const PipelineEvaluationRequest& request, const PipelineFlowState& state) override;

    /// Computes the time interval covered on the timeline by the given source animation frame.
    virtual TimeInterval frameTimeInterval(int frame) const;

public Q_SLOTS:

    /// Throws away the master data collection maintained by the source.
    void discardDataCollection();

private:

    /// Stores the master copy of the generated data collection.
    DECLARE_MODIFIABLE_REFERENCE_FIELD_FLAGS(DataOORef<const DataCollection>, dataCollection, setDataCollection, PROPERTY_FIELD_DONT_SAVE_RECOMPUTABLE_DATA | PROPERTY_FIELD_DONT_PROPAGATE_MESSAGES | PROPERTY_FIELD_NO_CHANGE_MESSAGE | PROPERTY_FIELD_NO_SUB_ANIM);

    /// The trajectory frame number that is currently stored in the source's data collection.
    DECLARE_MODIFIABLE_PROPERTY_FIELD_FLAGS(int{-1}, dataCollectionFrame, setDataCollectionFrame, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_NO_CHANGE_MESSAGE | PROPERTY_FIELD_DONT_SERIALIZE);

    /// Indicates that the user has made manual changes to the data objects in the source's data collection
    /// or to the visual elements. If this flag is set, we'll ask the user if these changes should be preserved when
    /// importing a whole new file or model into the source.
    DECLARE_PROPERTY_FIELD_FLAGS(bool{false}, userHasChangedDataCollection, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_NO_CHANGE_MESSAGE);
};

}   // End of namespace
