#ifndef INCLUDED_BOBCAT_FSOPTIONS_
#define INCLUDED_BOBCAT_FSOPTIONS_

#include <filesystem>

namespace FBB
{

class FS
{
    using CopyOpts      = std::filesystem::copy_options;
    using PermOpts      = std::filesystem::perm_options;

    public:
        enum FSOptions: unsigned
        {
            DEFAULT       = static_cast<unsigned>(CopyOpts::none), 
            NEW           = static_cast<unsigned>(CopyOpts::skip_existing), 
            REPLACE       = static_cast<unsigned>(CopyOpts::overwrite_existing),

                                                // cp if dest is older
            UPDATE        = static_cast<unsigned>(CopyOpts::update_existing),   

// RECURSIVE accepts CP_SYMLINKS, SKIP_SYMLINKS, ONLY_DIRS
                                                // recursively cp. subdirs
            RECURSIVE     = static_cast<unsigned>(CopyOpts::recursive), 

                                                // cp symlinks as symlinks
            CP_SYMLINKS   = static_cast<unsigned>(CopyOpts::copy_symlinks), 
            SKIP_SYMLINKS = static_cast<unsigned>(CopyOpts::skip_symlinks),

                                                // only cp the dirs
            ONLY_DIRS     = static_cast<unsigned>(CopyOpts::directories_only),

                                                // symlinks to d_path
            SYMLINK       = static_cast<unsigned>(CopyOpts::create_symlinks), 

            HARDLINK      = static_cast<unsigned>(              // 256
                                                CopyOpts::create_hard_links),
    
            FILE          = 512,            // call copy_file instead of copy
            CP_SYMLINK    = 1024,           // symlink to symlink
            NEW_SYMLINK   = 2048,           // create_(directory_)symlink
            NEW_LINK      = 4096,           // create_hardlink

            CP_MASK = (NEW_LINK << 1) - 1,

            RESET    = static_cast<unsigned>(PermOpts::replace),
            ADD      = static_cast<unsigned>(PermOpts::add),
            REMOVE   = static_cast<unsigned>(PermOpts::remove),
            NOFOLLOW = static_cast<unsigned>(PermOpts::nofollow),

//            PERM_MASK = (NEW_LINK << 1) - 1

    };

    friend CopyOpts cpOpts(FSOptions opts);
    friend PermOpts permOpts(FSOptions opts);
};

inline FS::CopyOpts cpOpts(FS::FSOptions opts)
{
    return static_cast<FS::CopyOpts>(opts);
}

inline FS::PermOpts permOpts(FS::FSOptions opts)
{
    return static_cast<FS::PermOpts>(opts);
}

inline FS::FSOptions operator|(FS::FSOptions lhs, FS::FSOptions rhs)
{
    return static_cast<FS::FSOptions>(
                static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)
            );
}

inline FS::FSOptions operator&(FS::FSOptions lhs, FS::FSOptions rhs)
{
    return static_cast<FS::FSOptions>(
                static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)
            );
}

inline FS::FSOptions operator^(FS::FSOptions lhs, FS::FSOptions rhs)
{
    return static_cast<FS::FSOptions>(
                static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)
            );
}

inline FS::FSOptions operator!(FS::FSOptions arg)
{
    return operator^(FS::FSOptions::CP_MASK, arg);
}

} // FBB        
#endif
