/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <iostream>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "MvPath.hpp"
#include "UtilitiesC.h"

static std::string user_dir = getenv("METVIEW_USER_DIRECTORY");
static Cached tmp_dir       = getenv("METVIEW_TMPDIR");
static Cached metv_dir      = getenv("METVIEW_DIR_SHARE");


std::string
GetUserDirectory()
{
    return user_dir;
}

std::string
MakeUserPath(const std::string& name)
{
    // If "user_dir" is already part of the input string then do nothing
    std::size_t found = name.find(user_dir);
    if (found != std::string::npos)
        return name;

    // Build the output string taking into consideration
    // if the input string has already the character '/'
    std::string fname = (name[0] == '/') ? user_dir + name : user_dir + "/" + name;

    return fname;
}

std::string
MakeUserDefPath(const char* name, bool absolutePath)
{
    std::string fname;
    if (absolutePath)
        fname += user_dir;

    fname += "/System/Defaults/";
    fname += name;

    return fname;
}

std::string
MakeUserPrefPath(const char* name)
{
    std::string fname = user_dir;
    fname += "/System/Preferences/";
    fname += name;

    return fname;
}

std::string
MakeSystemEtcPath(const std::string& name)
{
    std::string fname = (const char*)metv_dir + std::string("/etc/") + name;

    return fname;
}

std::string
MakeTmpPath(const char* name)
{
    std::string tmp = (const char*)tmp_dir;
    tmp += '/';
    tmp += name;

    return tmp;
}

Cached
MakeFilePath(const char* reqName)
{
    Cached path = user_dir.c_str() + Cached("/") + Cached(mdirname(reqName));

    return path;
}

const char*
MakeIconName(const char* path, const char* iconPrefix)
{
    // The new icon name is the next on the list
    return UtProgressiveName2(path, iconPrefix);
}

std::string
MakeIconNameFromPath(const std::string& path)
{
    std::string name;

    // If "user_dir" is not part of the input string then do nothing
    std::size_t found = path.find(user_dir);
    if (found == std::string::npos)
        return name;

    // Build the output string
    name = path.substr(found + user_dir.size());

    return name;
}

Cached
MakePrinterFileName(const Cached& path, const Cached& fileName)
{
    Cached newName;

    if (fileName == (Cached) "")
        newName = path + "PlotFile";
    else
        newName = fileName;

    return newName;
}

Cached
MakeTmpName(const Cached& iconPrefix)
{
    char* p        = UtRandomName(tmp_dir, iconPrefix);
    Cached newName = Cached(p);
    free(p);
    return newName;
}

Cached
MakeIconPath(const char* iconName)
{
    Cached iconPath = metv_dir + Cached("/icons/") + Cached(iconName) +
                      Cached(".icon");
    return iconPath;
}

// -- FUNCTION : FileCanBeOpened
//
// -- PURPOSE:   Tests if a file can be opened
//
// -- INPUT  :   filename and mode
//
// -- OUTPUT :   true/false

bool FileCanBeOpened(const char* filename, const char* mode)
{
    FILE* fp;

    // Can we open it in the desired mode ?
    if ((fp = fopen(filename, mode)) != nullptr) {
        fclose(fp);
        return true;
    }

    return false;
}

// -- FUNCTION : FileHasValidSize
//
// -- PURPOSE:   Tests if a file has size > 0
//
// -- INPUT  :   filename
//
// -- OUTPUT :   true/false

bool FileHasValidSize(const char* filename)
{
    struct stat buf;

    // Can we reach the file ?
    if (stat(filename, &buf) != 0)
        return false;

    // Does it have non-zero size ?
    if (buf.st_size == 0)
        return false;

    return true;
}

std::string
MakeProcessName(const char* name)
{
    // Build a process name according to the process id
    char buf[64];
    sprintf(buf, "%ld", (long)getpid());

    std::string fname(name);
    fname.append(buf);

    return fname;
}

std::string
FullPathName(const char* filename)
{
    std::string fullPath(filename);
    if (*filename != '/') {
        const char* pwd = getenv("PWD");
        fullPath        = std::string(pwd) + std::string("/") + fullPath;
    }

    return fullPath;
}

/*
std::string
UserTempCachePath()
{
std::string tmpdir = getenv("MV_TMPDIR_LINK");
std::string fname = user_dir + "/System/" + tmpdir + "/";

   return fname;
}
*/
std::string
MakeAbsolutePath(const char* path, const char* dir)
{
    // Consistency check
    if (!path)
        return dir ? std::string(dir) : std::string("");

    // If input parameter is already an absolute path then returns it.
    // Make sure that the file exists
    if (path[0] == '/' && FileCanBeOpened(path, "r"))
        return std::string(path);

    // Build an absolute path
    std::string upath;
    if (dir)
        upath = dir + std::string("/") + path;
    else
        upath = user_dir + path;  // uses METVIEW_USER_DIRECTORY

    return upath;
}

std::string
CreateTmpPath(const char* ref_name)
{
    // Create a full path string using tmp and ref_name
    std::string path = (const char*)MakeTmpName(ref_name);

    // Create directory
    const int dir_err = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    if (dir_err == -1)
        return std::string("");

    return path;
}

bool DeletePath(const char* path)
{
    std::string cmd = "rm -rf ";
    cmd += path;
    system(cmd.c_str());

    return true;
}
