//Copyright (c) 2022 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#ifndef PATH_PLANNING_G_CODE_PATH_H
#define PATH_PLANNING_G_CODE_PATH_H

#include "types/SpaceFillType.h"
#include "types/Ratio.h"
#include "types/Velocity.h"
#include "utils/IntPoint.h"
#include "TimeMaterialEstimates.h"

namespace cura52
{

    class GCodePathConfig;

    /*!
     * A class for representing a planned path.
     *
     * A path consists of several segments of the same type of movement: retracted travel, infill extrusion, etc.
     *
     * This is a compact premature representation in which are line segments have the same config, i.e. the config of this path.
     *
     * In the final representation (gcode) each line segment may have different properties,
     * which are added when the generated GCodePaths are processed.
     */
    class GCodePath
    {
    public:
        const GCodePathConfig* config; //!< The configuration settings of the path.
        std::string mesh_id; //!< Which mesh this path belongs to, if any. If it's not part of any mesh, the mesh ID should be 0.
        SpaceFillType space_fill_type; //!< The type of space filling of which this path is a part
        Ratio flow; //!< A type-independent flow configuration
        Ratio width_factor; //!< Adjustment to the line width. Similar to flow, but causes the speed_back_pressure_factor to be adjusted.
        Ratio speed_factor; //!< A speed factor that is multiplied with the travel speed. This factor can be used to change the travel speed.
        Ratio speed_back_pressure_factor; // <! The factor the (non-travel) speed should be multiplied with as a consequence of back pressure compensation.
        bool retract; //!< Whether the path is a move path preceded by a retraction move; whether the path is a retracted move path. 
        int  retract_move_icount;
        bool unretract_before_last_travel_move; //!< Whether the last move of the path should be preceded by an unretraction. Used to unretract in the last travel move before an outer wall
        bool perform_z_hop; //!< Whether to perform a z_hop in this path, which is assumed to be a travel path.
        bool perform_prime; //!< Whether this path is preceded by a prime (blob)
        bool skip_agressive_merge_hint; //!< Wheter this path needs to skip merging if any travel paths are in between the extrusions.
        std::vector<Point> points; //!< The points constituting this path.
        bool done; //!< Path is finished, no more moves should be added, and a new path should be started instead of any appending done to this one.

        bool spiralize; //!< Whether to gradually increment the z position during the printing of this path. A sequence of spiralized paths should start at the given layer height and end in one layer higher.

        double fan_speed; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise

        TimeMaterialEstimates estimates; //!< Naive time and material estimates
        Velocity speedSlowDownPath;
        bool entireLayerSlowdown;
        /*!
         * \brief Creates a new g-code path.
         *
         * \param config The line configuration to use when printing this path.
         * \param mesh_id The mesh that this path is part of.
         * \param space_fill_type The type of space filling of which this path is a
         * part.
         * \param flow The flow rate to print this path with.
         * \param width_factor A multiplier on the line width.
         * \param spiralize Gradually increment the z-coordinate while traversing
         * \param speed_factor The factor that the travel speed will be multiplied with
         * this path.
         */
        GCodePath(const GCodePathConfig& config, std::string mesh_id, const SpaceFillType space_fill_type, const Ratio flow, const Ratio width_factor, const bool spiralize, const Ratio speed_factor = 1.0);

        /*!
         * Whether this config is the config of a travel path.
         *
         * \return Whether this config is the config of a travel path.
         */
        bool isTravelPath() const;

        /*!
         * Get the material flow in mm^3 per mm traversed.
         *
         * \warning Can only be called after the layer height has been set (which is done while writing the gcode!)
         *
         * \return The flow
         */
        double getExtrusionMM3perMM() const;

        /*!
         * Get the actual line width (modulated by the flow)
         * \return the actual line width as shown in layer view
         */
        coord_t getLineWidthForLayerView() const;

        /*!
         * Set fan_speed
         *
         * \param fan_speed the fan speed to use for this path
         */
        void setFanSpeed(double fan_speed);

        /*!
         * Get the fan speed for this path
         * \return the value of fan_speed if it is in the range 0-100, otherwise the value from the config
         */
        double getFanSpeed() const;

        bool needSlowdown(int level) const;
    };

}//namespace cura52

#endif//PATH_PLANNING_G_CODE_PATH_H
