//
//  Coordinates.hpp
//  eagle0
//
//  Created by Dan Crosby on 3/6/18.
//  Copyright © 2018 none. All rights reserved.
//

#ifndef Coords_h
#define Coords_h

#include <sstream>

#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
#include "src/main/flatbuffer/net/eagle0/shardok/storage/coords.hpp"
#include "src/main/protobuf/net/eagle0/shardok/common/coords.pb.h"

namespace shardok {

using Coords = net::eagle0::shardok::storage::fb::Coords;
using CoordsProto = net::eagle0::shardok::common::Coords;

auto MakeCoordsProto(int row, int column) -> net::eagle0::shardok::common::Coords;

static inline auto IsUnplaced(const Coords &c) -> bool { return c.row() < 0 || c.column() < 0; }
static inline auto IsUnplaced(const CoordsProto &c) -> bool {
    return c.row() < 0 || c.column() < 0;
}

[[nodiscard]] static inline auto ToCoordsProto(const Coords &c) -> CoordsProto {
    return MakeCoordsProto(c.row(), c.column());
}

[[nodiscard]] static inline auto FromCoordsProto(const CoordsProto &cp) -> Coords {
    return {static_cast<MapIndex>(cp.row()), static_cast<MapIndex>(cp.column())};
}

}  // namespace shardok

namespace net::eagle0::shardok::storage::fb {
auto operator==(const Coords &lhs, const net::eagle0::shardok::common::Coords &rhs) -> bool;
}

namespace net::eagle0::shardok::common {
auto operator==(
        const net::eagle0::shardok::common::Coords &lhs,
        const net::eagle0::shardok::common::Coords &rhs) -> bool;
auto operator==(
        const net::eagle0::shardok::common::Coords &lhs,
        const net::eagle0::shardok::storage::fb::Coords &rhs) -> bool;
}  // namespace net::eagle0::shardok::common

namespace std {
template<>
struct hash<net::eagle0::shardok::common::Coords> {
    auto operator()(const net::eagle0::shardok::common::Coords &c) const -> size_t {
        return size_t(c.row() << 16 | c.column());
    }
};
}  // namespace std

#endif /* Coords_h */
