// Copyright Contributors to the DNF5 project.
// Copyright Contributors to the libdnf project.
// SPDX-License-Identifier: LGPL-2.1-or-later
//
// This file is part of libdnf: https://github.com/rpm-software-management/libdnf/
//
// Libdnf is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Libdnf 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with libdnf.  If not, see <https://www.gnu.org/licenses/>.


#ifndef LIBDNF5_RPM_TRANSACTION_CALLBACKS_HPP
#define LIBDNF5_RPM_TRANSACTION_CALLBACKS_HPP

#include "libdnf5/defs.h"
#include "libdnf5/rpm/nevra.hpp"

#include <cstdint>

namespace libdnf5::base {

class TransactionPackage;

}  // namespace libdnf5::base

namespace libdnf5::rpm {


/// Class represents one item in transaction set.
/// @deprecated This alias is confusing, do not use it.
using TransactionItem [[deprecated("This alias is confusing, do not use it.")]] = base::TransactionPackage;


/// The base class for Transaction callbacks.
/// User implements Transaction callbacks by inheriting this class and overriding its methods.
///
/// Typical order in which the transaction callbacks are called is:
///
/// - before_begin
/// - verification phase: verify_start, verify_progress, verify_stop
/// - script_start, script_stop, script_error for pre transaction scriplets
/// - preparation phase: transaction_start, transaction_progress, transaction_stop
/// - install packages: elem_progress, install_start, install_progress, install_stop, with their scriptlets
/// - remove packages: elem_progress, uninstall_start, uninstall_progress, uninstall_stop, with their scriptlets
/// - script_start, script_stop, script_error for post transaction scriplets
/// - after_complete
///
class LIBDNF_API TransactionCallbacks {
public:
    /// Scriptlet type
    // TODO(jrohel): Are all scriptlets types present and correct?
    enum class ScriptType {
        UNKNOWN,
        PRE_INSTALL,             // "%pre"
        POST_INSTALL,            // "%post"
        PRE_UNINSTALL,           // "%preun"
        POST_UNINSTALL,          // "%postun"
        PRE_TRANSACTION,         // "%pretrans"
        POST_TRANSACTION,        // "%posttrans"
        TRIGGER_PRE_INSTALL,     // "%triggerprein"
        TRIGGER_INSTALL,         // "%triggerin"
        TRIGGER_UNINSTALL,       // "%triggerun"
        TRIGGER_POST_UNINSTALL,  // "%triggerpostun"
        SYSUSERS,                // sysusers.d integration
        PREUN_TRANSACTION,       // "%preuntrans"
        POSTUN_TRANSACTION       // "%postuntrans"
    };

    /// @param type  scriptlet type
    /// @return  string representation of the scriptlet type
    static const char * script_type_to_string(ScriptType type) noexcept;

    explicit TransactionCallbacks();
    TransactionCallbacks(const TransactionCallbacks &) = delete;
    TransactionCallbacks(TransactionCallbacks &&) = delete;
    virtual ~TransactionCallbacks();

    TransactionCallbacks & operator=(const TransactionCallbacks &) = delete;
    TransactionCallbacks & operator=(TransactionCallbacks &&) = delete;

    /// Called right before the rpm transaction is run
    /// @param total Number of elements in the rpm transaction
    virtual void before_begin(uint64_t total);

    /// Called after the transaction run finished
    /// @param success Whether the rpm transaction was completed successfully
    virtual void after_complete(bool success);

    /// Report the package installation progress periodically.
    ///
    /// @param item The TransactionPackage class instance for the package currently being installed
    /// @param amount The portion of the package already installed
    /// @param total The disk space used by the package after installation
    virtual void install_progress(const libdnf5::base::TransactionPackage & item, uint64_t amount, uint64_t total);

    /// Installation of a package has started
    ///
    /// @param item The TransactionPackage class instance for the package currently being installed
    /// @param total The disk space used by the package after installation
    virtual void install_start(const libdnf5::base::TransactionPackage & item, uint64_t total);

    /// Installation of a package finished
    ///
    /// @param item The TransactionPackage class instance for the package currently being installed
    /// @param amount The portion of the package that has been installed
    /// @param total The disk space used by the package after installation
    virtual void install_stop(const libdnf5::base::TransactionPackage & item, uint64_t amount, uint64_t total);

    /// Preparation of a package has started.
    ///
    /// @param amount Index of the package currently being prepared. Items are indexed starting from 0.
    /// @param total The total number of packages in the transaction
    virtual void transaction_progress(uint64_t amount, uint64_t total);

    /// Preparation phase has started.
    ///
    /// @param total The total number of packages in the transaction
    virtual void transaction_start(uint64_t total);

    /// Preparation phase finished.
    ///
    /// @param total The total number of packages in the transaction
    virtual void transaction_stop(uint64_t total);

    /// Report the package removal progress periodically.
    ///
    /// @param item The TransactionPackage class instance for the package currently being removed
    /// @param amount The portion of the package already uninstalled
    /// @param total The disk space freed by the package after removal
    virtual void uninstall_progress(const libdnf5::base::TransactionPackage & item, uint64_t amount, uint64_t total);

    /// Removal of a package has started
    ///
    /// @param item The TransactionPackage class instance for the package currently being removed
    /// @param total The disk space freed by the package after removal
    virtual void uninstall_start(const libdnf5::base::TransactionPackage & item, uint64_t total);

    /// Removal of a package finished
    ///
    /// @param item The TransactionPackage class instance for the package currently being removed
    /// @param amount The portion of the package already uninstalled
    /// @param total The disk space freed by the package after removal
    virtual void uninstall_stop(const libdnf5::base::TransactionPackage & item, uint64_t amount, uint64_t total);

    /// Unpacking of the package failed.
    ///
    /// @param item The TransactionPackage class instance representing the package that failed to unpack
    virtual void unpack_error(const libdnf5::base::TransactionPackage & item);

    /// cpio error during the package installation. Currently not used by librpm.
    ///
    /// @param item The TransactionPackage class instance representing the package that caused the error
    virtual void cpio_error(const libdnf5::base::TransactionPackage & item);

    /// Execution of the rpm scriptlet finished with error
    ///
    /// @param item The TransactionPackage class instance for the package that owns the executed or triggered scriptlet. It can be `nullptr` if the scriptlet owner is not part of the transaction.
    /// @param nevra Nevra of the package that owns the executed or triggered scriptlet.
    /// @param type Type of the scriptlet
    /// @param return_code The return code of the scriptlet execution
    virtual void script_error(
        const libdnf5::base::TransactionPackage * item, Nevra nevra, ScriptType type, uint64_t return_code);

    /// Execution of the rpm scriptlet has started
    ///
    /// @param item The TransactionPackage class instance for the package that owns the executed or triggered scriptlet. It can be `nullptr` if the scriptlet owner is not part of the transaction (e.g., a package installation triggered an update of the man database, owned by man-db package).
    /// @param nevra Nevra of the package that owns the executed or triggered scriptlet.
    /// @param type Type of the scriptlet
    virtual void script_start(const libdnf5::base::TransactionPackage * item, Nevra nevra, ScriptType type);

    /// Execution of the rpm scriptlet finished without critical error
    ///
    /// @param item The TransactionPackage class instance for the package that owns the executed or triggered scriptlet. It can be `nullptr` if the scriptlet owner is not part of the transaction.
    /// @param nevra Nevra of the package that owns the executed or triggered scriptlet.
    /// @param type Type of the scriptlet
    /// @param return_code The return code of the scriptlet execution
    virtual void script_stop(
        const libdnf5::base::TransactionPackage * item, Nevra nevra, ScriptType type, uint64_t return_code);

    /// The installation/removal process for the item has started
    ///
    /// @param amount Index of the package currently being processed. Items are indexed starting from 0.
    /// @param total The total number of packages in the transaction
    virtual void elem_progress(const libdnf5::base::TransactionPackage & item, uint64_t amount, uint64_t total);

    /// Verification of a package files has started.
    ///
    /// @param amount Index of the package currently being verified. Items are indexed starting from 0.
    /// @param total The total number of packages to verify
    virtual void verify_progress(uint64_t amount, uint64_t total);

    /// Packages files verification phase has started. In this phase the signature of packages are verified.
    ///
    /// @param total The total number of packages to verify
    virtual void verify_start(uint64_t total);

    /// Packages files verification phase finished.
    ///
    /// @param total The total number of packages to verify
    virtual void verify_stop(uint64_t total);
};


}  // namespace libdnf5::rpm

#endif  // LIBDNF5_RPM_TRANSACTION_CALLBACKS_HPP
