/*
 *       File name:  aghermann/expdesign/dirlevel.cc
 *         Project:  Aghermann
 *          Author:  Andrei Zavada <johnhommer@gmail.com>
 * Initial version:  2013-09-12
 *
 *         Purpose:  experimental design primary classes: CStorablePPack
 *
 *         License:  GPL
 */


#include <dirent.h>
#include <errno.h>
#include <string>

#include "common/string.hh"
#include "common/fs.hh"
#include "aghermann/globals.hh"
#include "expdesign.hh"
#include "dirlevel.hh"

using namespace std;
using namespace agh;


int
agh::
simple_scandir_filter( const struct dirent *e)
{
        return e->d_type == DT_REG;
}



const char*
agh::
exp_dir_level_s( TExpDirLevel x)
{
        switch (x) {
        case TExpDirLevel::transient:   return "~";
        case TExpDirLevel::session:     return "[D]";
        case TExpDirLevel::subject:     return "[J]";
        case TExpDirLevel::group:       return "[G]";
        case TExpDirLevel::experiment:  return "[E]";
        case TExpDirLevel::user:        return "[U]";
        case TExpDirLevel::system:      return "<S>";
        default: return "?";
        }
}



string
agh::
level_corrected_subdir( TExpDirLevel level, const string& subdir)
{
        auto undot = [] ( const string& S) -> string { return (S[0] == '.') ? string(S).erase(0,1) : S; };
        switch (level) {
        case TExpDirLevel::user:
        case TExpDirLevel::system:
                return undot(subdir);

        case TExpDirLevel::transient:
        case TExpDirLevel::session:
        case TExpDirLevel::subject:
        case TExpDirLevel::group:
        case TExpDirLevel::experiment:
        default:
                return subdir;
        }
}




string
CStorablePPack::
path() const
{
        string append = string("/") + level_corrected_subdir() + "/" + name;

        switch (level) {
        case TExpDirLevel::transient:
                return move(string("/tmp") + append);

        case TExpDirLevel::session:
        case TExpDirLevel::subject:
        case TExpDirLevel::group:
        case TExpDirLevel::experiment:
                return move(ED.make_dirname( level, level_id) + append);

        case TExpDirLevel::user:
                return move(str::sasprintf( "%s/.local/share/aghermann%s", getenv("HOME"), append.c_str()));

        case TExpDirLevel::system:
                return move(str::sasprintf( "%s/aghermann/%s", PACKAGE_DATADIR, append.c_str()));
        }

        throw invalid_argument ("bad TExpDirLevel");
}

int
CStorablePPack::
load()
{
        libconfig::Config C;

        try {
                C.readFile( path().c_str());
                config.get( C, agh::global::default_log_facility, agh::TThrowOption::do_throw);
                saved = true;

                return 0;

        } catch (...) {
                return -1;
        }
}


int
CStorablePPack::
save()
{
        if ( saved || level == TExpDirLevel::transient || level == TExpDirLevel::system )
                return 0;

        string p = path();
        if ( fs::mkdir_with_parents( fs::dirname(p)) ) {
                APPLOG_WARN ("mkdir(\"%s\") failed: %s", p.c_str(), strerror(errno));
                return -1;
        }

        try {
                libconfig::Config C;
                config.put( C, agh::global::default_log_facility);
                C.writeFile( p.c_str());
                saved = true;

                return 0;

        } catch (...) {
                return -1;
        }
}



int
CStorablePPack::
delete_file() const
{
        return unlink( path().c_str());
}


string
CStorablePPack::
serialize() const
{
        return move(
                str::sasprintf(
                        "%s/%s %s (%s/%s/%s)",
                        subdir.c_str(), name.c_str(), exp_dir_level_s(), level_id.g.c_str(), level_id.j.c_str(), level_id.d.c_str()));
}


// Local Variables:
// Mode: c++
// indent-tabs-mode: nil
// tab-width: 8
// c-basic-offset: 8
// End:
