//
// Created by Dan Crosby on 10/13/22.
//

#ifndef EAGLE0_FIXEDACTIONPOINTDISTANCES_HPP
#define EAGLE0_FIXEDACTIONPOINTDISTANCES_HPP

#include <utility>
#include <vector>

#include "src/main/cpp/net/eagle0/shardok/library/BattalionType.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistances.hpp"

namespace shardok {

using std::vector;
using BattalionTypeSPtr = std::shared_ptr<const BattalionType>;

class FixedActionPointDistances final : public ActionPointDistances {
public:
    struct CreationResult {
        std::shared_ptr<FixedActionPointDistances> apd;
        bool loadedFromFile;
    };

private:
    vector<vector<DIST_T>> distances;

    inline static string cacheDirectory = "";

    // Private constructor - use Create factory method instead
    explicit FixedActionPointDistances(const HexMap *map, int columnCount);

public:
    static void SetCacheDirectory(const string &newDir);

    // Factory method to create FixedActionPointDistances with metadata
    static auto Create(
            const HexMap *map,
            int64_t terrainTypesHash,
            int64_t modifierHash,
            const BattalionTypeSPtr &battalionType,
            bool includeBravingWater,
            int braveWaterActionPointCost = -1) -> CreationResult;

    ~FixedActionPointDistances() override = default;

    [[nodiscard]] auto Distance(const int fromIndex, const int toIndex) const -> DIST_T override {
        return distances[fromIndex][toIndex];
    }

    [[nodiscard]] auto Distance(const Coords &from, const Coords &to) const -> DIST_T override {
        return Distance(ToIndex(from), ToIndex(to));
    }

    friend struct CreationResult;
};

}  // namespace shardok

#endif  // EAGLE0_FIXEDACTIONPOINTDISTANCES_HPP
