#ifndef INCLUDED_BOBCAT_STAT_
#define INCLUDED_BOBCAT_STAT_

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>

#include <bobcat/datetime>
#include <bobcat/gs>

namespace FBB
{

class User;

class Stat: public GS__
{
    struct stat d_stat;
    bool d_errno;
    std::string d_name;

    public:
        typedef struct stat stat;   // Defines Stat::stat for clients

        enum Combine
        {
          ALL,
          ANY,
        };

        enum SpecialMode
        {
          SUID = 04000,
          SGID = 02000,
            SB = 01000,
        };

        enum Mode
        {
            UR =  0400,
            UW =  0200,
            UX =  0100,

            GR =   040,
            GW =   020,
            GX =   010,

            OR =    04,
            OW =    02,
            OX =    01,

          READ =  UR | GR | OR,
         WRITE =  UW | GW | OW,
          EXEC =  UX | GX | OX,

           RWX =  0777,
        };

        enum Lstat
        {
            LStat
        };

        Stat();                                                     // 1.cc
        Stat(Stat const &other) = default;
        Stat(Stat &&tmp);                                           // 2.cc

        explicit Stat(std::string const &name);                     // 3.cc
        Stat(Lstat, std::string const &name);                       // 4.f
        Stat(std::string const &name, std::string const &pathlist); // 5.f
        Stat(Lstat, std::string const &name,                        // 6.f
             std::string const &pathlist); 


        Stat &operator=(Stat const &other) = default;
        Stat &operator=(Stat &&tmp);

        bool access(User const &user, size_t mode, 
                                       bool useEffective = true) const;
        DateTime lastAccess() const;                                    // .f
        DateTime lastChange() const;                                    // .f
        DateTime lastModification() const;                              // .f
        Type type() const;                                              // .f
        bool isType(Type probe);                                        // .f
        bool mode(size_t mode, Combine combi = ALL) const;

        bool set(std::string const &name);                              // 1.cc
        bool set(Lstat, std::string const &name);                       // 2.f

        bool set(std::string const &name, std::string const &pathlist); // 3.cc
        bool set(Lstat, std::string const &name,                        // 4.f
                 std::string const &pathlist);

        bool specialMode(size_t specialMode, Combine combi = ALL) const;
        off_t size() const;                                             // .f
        operator bool() const;                                          // .f
        size_t blockSize() const;                                       // .f
        size_t device() const;                                          // .f
        size_t deviceType() const;                                      // .f
        size_t error() const;                                           // .f
        size_t gid() const;                                             // .f
        size_t inode() const;                                           // .f
        size_t mode() const;                                            // .f
        size_t nBlocks() const;                                         // .f
        size_t nLinks() const;                                          // .f
        size_t uid() const;                                             // .f
        stat const &statStruct() const;                                 // .f
        std::string const &name();                                      // .f
        std::string modeStr() const;
        std::string path();
        std::string typeStr() const;

    private:
        void init(int (*statFun)(char const *, stat *));
        bool setPath(int (*statFun)(char const *, stat *),
                     std::string const &name, std::string const &pathlist);
        bool set(int (*statFun)(char const *, stat *),                  // 5.cc
                 std::string const &name);
};

#include "stat6.f"
#include "stat4.f"
#include "stat5.f"
#include "blocksize.f"
#include "device.f"
#include "devicetype.f"
#include "error.f"
#include "gid.f"
#include "inode.f"
#include "istype.f"
#include "lastaccess.f"
#include "lastchange.f"
#include "lastmodification.f"
#include "mode.f"
#include "name.f"
#include "nblocks.f"
#include "nlinks.f"
#include "opbool.f"
#include "set2.f"
#include "set4.f"
#include "size.f"
#include "statstruct.f"
#include "type.f"
#include "uid.f"

} // FBB
        
#endif
