/*****************************************************************************
 * Copyright (c) 2002-2020 MBARI
 * Monterey Bay Aquarium Research Institute, all rights reserved.
 *****************************************************************************
 * @file    oaUtils.cc
 * @authors r. henthorn
 * @date    12/01/2020
 * @brief   Obstacle Avoidance utility functions
 *
 * Project: LRAUV Obstacle Avoidance
 * Summary: See @brief
 *****************************************************************************/
/*****************************************************************************
 * Copyright Information:
 * Copyright 2002-2020 MBARI
 * Monterey Bay Aquarium Research Institute, all rights reserved.
 *
 * Terms of Use:
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option)
 * any later version. You can access the GPLv3 license at
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details (http://www.gnu.org/licenses/gpl-3.0.html).
 *
 * MBARI provides the documentation and software code "as is", with no
 * warranty, express or implied, as to the software, title, non-infringement
 * of third party rights, merchantability, or fitness for any particular
 * purpose, the accuracy of the code, or the performance or results which you
 * may obtain from its use. You assume the entire risk associated with use of
 * the code, and you agree to be responsible for the entire cost of repair or
 * servicing of the program with which you are using the code.
 *
 * In no event shall MBARI be liable for any damages,whether general, special,
 * incidental or consequential damages, arising out of your use of the
 * software, including, but not limited to,the loss or corruption of your data
 * or damages of any kind resulting from use of the software, any prohibited
 * use, or your inability to use the software. You agree to defend, indemnify
 * and hold harmless MBARI and its officers, directors, and employees against
 * any claim,loss,liability or expense,including attorneys' fees,resulting from
 * loss of or damage to property or the injury to or death of any person
 * arising out of the use of the software.
 *
 * The MBARI software is provided without obligation on the part of the
 * Monterey Bay Aquarium Research Institute to assist in its use, correction,
 * modification, or enhancement.
 *
 * MBARI assumes no responsibility or liability for any third party and/or
 * commercial software required for the database or applications. Licensee
 * agrees to obtain and maintain valid licenses for any additional third party
 * software required.
 *****************************************************************************/

/******************************
 * Headers
 ******************************/

#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <getopt.h>
#include <libgen.h>
#include <sys/stat.h>

#include "oaUtils.h"
#include "macrologger.h"

/******************************
 * Macros
 ******************************/

/******************************
 * Code
 ******************************/

// setup the env LOG_DIR_ENV using setenv() for use by other components use
// log_home as the base folder and create a new uniquely named folder
// for this run
void setLogDir(const char *log_dir_env, const char *log_home)
{
   // do something useful when passed poor parameters
   if (NULL == log_dir_env) log_dir_env = "";   // empty but non-null env var
   if (NULL == log_home) log_home = ".";        // use pwd as default log home

   // now evaluate the env var
   const char *envval = getenv(log_dir_env)? getenv(log_dir_env) : "NULL";
   LOG_INFO("Using ENV var \"%s\" == \"%s\" and log home \"%s\"",
             log_dir_env, envval, log_home);

   // if log_home is defined and exists, use that as the base log directory.
   // otherwise, use the local directory as the base log directory.
   struct stat statbuf;
   const char* logdir = log_home;
   if (0 != stat(logdir, &statbuf)) logdir = ".";     // doesn't exist

   // create a unique sub-directory in the base directory for logs
   // use pattern yyyy.day.nnn like the Dorado system
   // first build the yyyy.day of the directory name
   int length = strlen(logdir) + strlen("yyyy.day.000000") + 10;
   char *newlogdir = (char*)malloc(length);
   time_t t = time(NULL);
   struct tm *now = gmtime(&t);
   sprintf(newlogdir,"%s/%4d.%03d",logdir, now->tm_year+1900, now->tm_yday);
   LOG_INFO("Using %s as base log directory name", newlogdir);

   // now make it unique by adding nnn
   if (0 == uniqueName(newlogdir, length))
   {
      // if unique name, set the AUV_LOG_DIR and create the directory
      mkdir(newlogdir,S_IREAD|S_IWRITE|S_IEXEC|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
   }

   // set the env variable if one exists
   if (strlen(log_dir_env) > 0)
   {
      LOG_INFO("Setting %s to %s", log_dir_env, newlogdir);
      setenv(log_dir_env, newlogdir, 1);
   }

   LOG_INFO("Using %s as log directory", newlogdir);

   free(newlogdir);
}

// create a unique filename from the given path by appending 3-digit decimal
// values to the path (e.g., ".000"). Arguments are a char array with basic
// path and the size of the array. New pathname is placed in path array.
// uniqueName() does not create the file.
// Returns 0 if successful.
// Returns > 0 if folder in path does not exist.
// Returns < 0 when the suffix is more than MAX or the pathlen is too short.
// Examples:
// place "/home/logs/test_app" in path, assume that file exists
// char path[PATHLEN]; sprintf(path, "/home/logs/test_app");
// place "/home/logs/test_app.000" in path
// uniqueName(path, PATHLEN);
#define MAX_APPEND_NUM  99999
#define TOO_SHORT -1
#define NON_EXIST  1
#define UNIQUE     0
int uniqueName(char path[], size_t pathlen)
{
   // size of path must be more than zero
   if (!(pathlen > 0))
   {
      return TOO_SHORT;
   }

   int status = 0;
   int i = 0;
   struct stat  statbuf;
   char *copy = strdup(path);
   // ensure that the directory for the file exists
   // stat() returns 0 if the file specified in the first argument exists
   if (0 != stat(dirname(copy), &statbuf))
   {
      status = NON_EXIST;
   }
   else
   {
      delete copy;
      copy = strdup(path);
      // file in path exists
      // attempt to create a unique path by appending ".000", ".001", ...
      for (i = 0; i <= MAX_APPEND_NUM; i++)
      {
         int len = (int)pathlen;
         // done if pathlen was exceeded
         if (len == snprintf(path, pathlen, "%s.%03d", copy, i))
         {
            status = TOO_SHORT;
            break;
         }
         // done if path is unique
         if (0 != stat(path, &statbuf))
         {
            status = UNIQUE;
            break;
         }
      }
      // done if numbers were exhausted
      if (i > MAX_APPEND_NUM) status = TOO_SHORT;
   }

   delete copy;
   return status;
}
