///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (c) 2000-2018 Ericsson Telecom AB                               //
//                                                                           //
// All rights reserved. This program and the accompanying materials          //
// are made available under the terms of the Eclipse Public License v2.0     //
// which accompanies this distribution, and is available at                  //
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html                                 //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <glob.h>
#include <linux/limits.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "EPTF_CLL_DsRestAPI_Functions.hh"
#include "EPTF_CLL_DsRestAPI_DSServer_Functions.hh"
#include "EPTF_CLL_DsRestAPI_HTTPServer_Functions.hh"

void EPTF__CLL__DsRestAPI__Filter__Functions::ef__EPTF__DsRestAPI__replaceAllIfMatches(
  CHARSTRING& pl__toReplace,
  const CHARSTRING& pl__replaceTemplate,
  const CHARSTRING& pl__replaceWith
) {
  const char* templatepos;
  int lenghtOfTemplate = pl__replaceTemplate.lengthof();
  const char* inputPtr = (const char*)pl__toReplace;
  CHARSTRING retval = "";
  const char* pos=inputPtr;
  const char* endOfInput = inputPtr+pl__toReplace.lengthof();
  
  while(pos<endOfInput) {
    // search for replaceString:
    templatepos = strstr(pos,pl__replaceTemplate);
    if (templatepos!=NULL) {
      retval+=CHARSTRING(templatepos-pos,pos);
      retval+=pl__replaceWith;
      pos=templatepos+lenghtOfTemplate;
    } else {
      retval+=CHARSTRING(endOfInput-pos,pos);
      pos=endOfInput;
    }
  }
  pl__toReplace=retval;
}

EPTF__CLL__Common__Definitions::EPTF__CharstringList EPTF__CLL__DsRestAPI__HTTPServer__Functions::ef__EPTF__DsRestAPI__HTTPServer__FIO__listDir(const CHARSTRING& pl__dirName) {
  EPTF__CLL__Common__Definitions::EPTF__CharstringList retVal;
  retVal.set_size(0);
  
  glob_t glob_result;
  glob((const char*)(pl__dirName+"*"),GLOB_TILDE,NULL,&glob_result);
  for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
    retVal[i] = glob_result.gl_pathv[i];
  }  
  
  return retVal;
}

int remove_directory(const char *path) {
  int errorCode = 0;

  DIR *directory = opendir(path);
  size_t pathLength = strlen(path);

  if (directory) {
    struct dirent *entry;
    while (errorCode == 0 && (entry = readdir(directory))) {
      if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
        continue;
      }

      size_t len = pathLength + strlen(entry->d_name) + 2; 
      char *buf = new char[len];

      if (buf) {
        struct stat statbuf;
        snprintf(buf, len, "%s/%s", path, entry->d_name);
        if (!lstat(buf, &statbuf)) {
          if (S_ISDIR(statbuf.st_mode)) {
             errorCode = remove_directory(buf);
          } else {
             errorCode = unlink(buf);
          }
        }

        delete[] buf;
      } else {
        errorCode = -1;
      }
    }
 
    closedir(directory);
  } else {
    errorCode = -1;
  }

  if (errorCode == 0) {
    errorCode = rmdir(path);
  }

  return errorCode;
}

INTEGER EPTF__CLL__DsRestAPI__HTTPServer__Functions::ef__EPTF__DsRestAPI__FIO__deleteResource(const CHARSTRING& pl__path) {
  struct stat statbuf;

  if (!lstat(pl__path, &statbuf)) {
    if (S_ISDIR(statbuf.st_mode)) {
       return remove_directory(pl__path);
    } else {
       return unlink(pl__path);
    }
  } else {
      return 0;
  }
}

INTEGER EPTF__CLL__DsRestAPI__Functions::ef__EPTF__DsRestAPI__FIO__readlink(const CHARSTRING& pl__relPath, CHARSTRING& pl__absPath) {
  int retVal;
  char *buf = new char[PATH_MAX];
  char* path = realpath(pl__relPath, buf);
  if (path == NULL) {
    retVal = -1;
  } else {
    pl__absPath = CHARSTRING (strlen(buf), buf);
    retVal = 0;
  }
  delete[] buf;
  return retVal;
}

INTEGER EPTF__CLL__DsRestAPI__Functions::ef__EPTF__DsRestAPI__FIO__symlink(const CHARSTRING& pl__path1, const CHARSTRING& pl__path2) {
  return symlink(pl__path1, pl__path2);
}

static char stat2FileType(struct stat s) {
    switch (s.st_mode & S_IFMT) {
        case S_IFBLK:  return 'b'; break; // block device
        case S_IFCHR:  return 'c'; break; // character device
        case S_IFDIR:  return 'd'; break; // directory
        case S_IFIFO:  return 'p'; break; // fifo, pipe, named pipe
        case S_IFLNK:  return 'l'; break; // symlink
        case S_IFREG:  return 'f'; break; // regular file
        case S_IFSOCK: return 's'; break; // socket
        default:       return '?'; break; // unknown
    }
}

EPTF__CLL__DsRestAPI__HTTPServer__Definitions::EPTF__DsRestAPI__HTTPServer__FileInfoList EPTF__CLL__DsRestAPI__HTTPServer__Functions::ef__EPTF__DsRestAPI__HTTPServer__FIO__listDirWithStat(const CHARSTRING& pl__dirName) {
  EPTF__CLL__DsRestAPI__HTTPServer__Definitions::EPTF__DsRestAPI__HTTPServer__FileInfoList retVal;
  retVal.set_size(0);

  glob_t glob_result;
  glob((const char*)(pl__dirName+"*"),GLOB_TILDE | GLOB_NOSORT,NULL,&glob_result);
  for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
    struct stat fileInfo;
    retVal[i].fileName() = glob_result.gl_pathv[i];
    // With lstat(), we'll know it is a symlink.
    int statOk = !lstat(retVal[i].fileName(), &fileInfo);
    char isLink = 0;
    if(statOk) { // OK
        if(S_ISLNK(fileInfo.st_mode)) { // It's a symlink, now we stat() the linked file.
            isLink = 1;
            statOk = !stat(retVal[i].fileName(), &fileInfo);
        }
    }
    
    if(statOk) {
        char modestr[3];
        sprintf(modestr, "%c%c", (isLink?'l':'-'), stat2FileType(fileInfo));
        retVal[i].contentType() = modestr;
        retVal[i].size() = fileInfo.st_size;
        retVal[i].timestamp() = fileInfo.st_mtime;
    } else { // FAIL
        retVal[i].contentType() = "??";
        retVal[i].size() = -1;
        retVal[i].timestamp() = -1;
    }
  }
  globfree(&glob_result);
  
  return retVal;
}

// end of file
