#pragma once
#include "common.hpp"
#include <sys/stat.h>


class Attr {
    private:
        struct stat ss;
        static Attr* getInst(Attr*);

    public:
        static Attr* getInst(int);
        static Attr* getInst(int, const char*);
        static Attr* getInst(const struct stat&);

        typedef enum {
            SAME,              // relevant metadata equal
            FAIL,              // unrecoverable situation, no sense in asking the user
            ATTR_CONFLICT,     // have to ask client
            ATTR_THIS,         // take my attrs
            ATTR_THAT,         // take arg's attrs
            FULL_CONFLICT,     // have to ask client
            FULL_THIS,         // take my content and attrs
            FULL_THAT,         // take arg's content and attrs
            FULL_OR_ATTR_THIS, // should replace, but content might be the same
            FULL_OR_ATTR_THAT
        } merge_t;
        merge_t cmp(const Attr*) const;

        INLINE bool is_dir() const { return S_ISDIR(ss.st_mode); }
        INLINE bool is_reg() const { return S_ISREG(ss.st_mode); }
        INLINE off_t size() const { return ss.st_size; }
        INLINE ino_t ino() const { return ss.st_ino; }
        INLINE mode_t mode() const { return ss.st_mode & ~S_IFMT; }
        INLINE uid_t uid() const { return ss.st_uid; }
        INLINE gid_t gid() const { return ss.st_gid; }
        INLINE const struct timespec& ctime() const { return ss.st_ctim; }
        INLINE const struct timespec& mtime() const { return ss.st_mtim; }

        bool apply_to(int) const;
};


bool operator<(const struct timespec&, const struct timespec&);
bool operator>(const struct timespec&, const struct timespec&);
bool operator==(const struct timespec&, const struct timespec&);
bool operator!=(const struct timespec&, const struct timespec&);