/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright 2019 Danny Robson <danny@nerdcruft.net>
 */

#pragma once

#include "base.hpp"

#include <cstddef>


///////////////////////////////////////////////////////////////////////////////
namespace cruft::coord {
    /// A StrictWeakOrder over coordinate types.
    template <typename CoordT = void>
    struct ordering;


    /// A StrictWeakOrder over coordinate types.
    ///
    /// The comparison operates across successive elements of the two
    /// coordinates.
    template <typename CoordT>
    struct ordering {
        bool operator() (
            CoordT const &a,
            CoordT const &b
        ) const noexcept {
            for (std::size_t i = 0; i < CoordT::elements; ++i) {
                if (a[i] < b[i])
                    return true;
                else if (a[i] > b[i])
                    return false;
            }

            return false;
        }
    };


    /// A StrictWeakOrder over coordinate types.
    ///
    /// Deduction is deferred until the function is called, in the same way
    /// that std::less<> operates.
    template <>
    struct ordering<void> {
        template <typename CoordT>
        bool operator() (CoordT const &a, CoordT const &b) const noexcept
        {
            return ordering<CoordT> {} (a, b);
        }
    };
}