/*
 * 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 "except.hpp"

#include <sys/types.h>
#include <ifaddrs.h>


namespace cruft::posix {
    auto
    interface (void)
    {
        struct iterator {
            explicit iterator (ifaddrs *_cursor) noexcept
              : cursor (_cursor)
            { ; }

            ifaddrs *cursor;

            decltype (auto) operator*  (void) { return *cursor; }
            decltype (auto) operator-> (void) { return  cursor; }

            iterator& operator++ (void)
            {
                cursor = cursor->ifa_next;
                return *this;
            }

            bool operator== (iterator const &rhs) const noexcept { return cursor == rhs.cursor; }
            bool operator!= (iterator const &rhs) const noexcept { return cursor != rhs.cursor; }
        };


        class container {
        public:
            container ()
            {
                error::try_call (getifaddrs, &m_data);
            }

            ~container ()
            {
                if (m_data)
                    freeifaddrs (m_data);
            }


            container (container &&rhs) noexcept:
                m_data (std::exchange (rhs.m_data, nullptr))
            { ; }

            container& operator= (container &&rhs) noexcept
            {
                std::swap (m_data, rhs.m_data);
                return *this;
            }

            container (container const&) = delete;
            container& operator= (container const&) = delete;

            auto begin (void) { return iterator (m_data); }
            auto end   (void) { return iterator (nullptr); }

            ifaddrs *m_data;
        };

        return container ();
    }
}