BareGit
#pragma once

#include <string>
#include <utility>
#include <vector>

#include <mw/url.hpp>

/// Kind of one path segment supplied to UrlBuilder.
enum class RouteSegmentKind
{
    /// Trusted application route text.
    LITERAL,

    /// One value encoded as a single path segment.
    DYNAMIC,

    /// Route-registration placeholder accepted only by requestPath().
    PLACEHOLDER
};

/// One trusted literal, encoded value, or route-registration placeholder.
struct RouteSegment
{
    /// Interpretation applied to value.
    RouteSegmentKind kind;

    /// Unencoded segment text or placeholder name.
    std::string value;
};

/// Ordered query parameters encoded by UrlBuilder.
using QueryParameters =
    std::vector<std::pair<std::string, std::string>>;

/// Build base-aware URLs from trusted literal and encoded dynamic segments.
class UrlBuilder
{
public:
    /// Construct a builder from a validated absolute HTTP or HTTPS base URL.
    explicit UrlBuilder(mw::URL base_url);

    /// Return an absolute URL for the supplied route segments.
    std::string absolute(
        const std::vector<RouteSegment>& segments,
        const QueryParameters& query = {}) const;

    /// Append one validated relative path beneath a static-mount prefix.
    std::string absoluteFromRelativePath(
        const std::vector<RouteSegment>& mount_prefix,
        const std::string& relative_path,
        const QueryParameters& query = {}) const;

    /// Return only the base-prefixed server request path.
    std::string requestPath(
        const std::vector<RouteSegment>& segments) const;

private:
    mw::URL base_url_;
};