/*
 * Copyright 2015 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "basics/fileutils.h"
#include <dirent.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include "glog/logging.h"

#include "basics/sprcodes.h"
#include "basics/spconsts.h"

std::string FileUtils::baseName(const std::string& path) {
  return path.substr(path.find_last_of(constPathSeparator) + 1);
}

sp_int32 FileUtils::makeDirectory(const std::string& directory) {
  struct stat st;

  // get the directory name stats
  auto retcode = ::stat(directory.c_str(), &st);

  // check for any errors
  if (retcode == -1) {
    if (errno == ENOENT) {
      if (::mkdir(directory.c_str(), 0700) != 0) {
        PLOG(ERROR) << "Unable to create directory " << directory;
        return SP_NOTOK;
      }
      return SP_OK;
    }

    PLOG(ERROR) << "Unable to create directory " << directory;
    return SP_NOTOK;
  }

  return S_ISDIR(st.st_mode) ? SP_OK : SP_NOTOK;
}

sp_int32 FileUtils::removeFile(const std::string& filepath) {
  if (::unlink(filepath.c_str()) != 0) {
    PLOG(ERROR) << "Unable to delete file " << filepath;
    return SP_NOTOK;
  }
  return SP_OK;
}

sp_int32 FileUtils::removeRecursive(const std::string& directory, bool delete_self) {
  auto dir = ::opendir(directory.c_str());
  if (dir == nullptr) {
    PLOG(ERROR) << "opendir failed for " << directory;
    return SP_NOTOK;
  }

  // list all dir contents
  struct dirent* entry = nullptr;
  while ((entry = ::readdir(dir)) != nullptr) {
    auto current_dir = std::string(entry->d_name).compare(constCurrentDirectory);
    auto parent_dir = std::string(entry->d_name).compare(constParentDirectory);

    if (current_dir != 0 && parent_dir != 0) {
      auto path = directory + constPathSeparator + std::string(entry->d_name);
      if (entry->d_type == DT_DIR) {
        if (removeRecursive(path, true) == SP_NOTOK) return SP_NOTOK;
      } else {
        if (::unlink(path.c_str()) != 0) {
          PLOG(ERROR) << "Unable to delete " << path;
          return SP_NOTOK;
        }
      }
    }
  }

  ::closedir(dir);

  // now delete the dir
  if (delete_self) {
    if (::rmdir(directory.c_str()) != 0) {
      PLOG(ERROR) << "Unable to delete directory " << directory;
      return SP_NOTOK;
    }
  }

  return SP_OK;
}

sp_int32 FileUtils::listFiles(const std::string& directory, std::vector<std::string>& files) {
  auto dir = ::opendir(directory.c_str());
  if (dir != nullptr) {
    struct dirent* ent;
    while ((ent = ::readdir(dir)) != nullptr) {
      auto current_dir = std::string(ent->d_name).compare(constCurrentDirectory);
      auto parent_dir = std::string(ent->d_name).compare(constParentDirectory);
      if (current_dir != 0 && parent_dir != 0) {
        files.push_back(ent->d_name);
      }
    }

    ::closedir(dir);
    return SP_OK;
  }

  // log errors that we could not open the dir
  PLOG(ERROR) << "Unable to open directory " << directory;
  return SP_NOTOK;
}

std::string FileUtils::readAll(const std::string& file) {
  std::ifstream in(file.c_str(), std::ifstream::in | std::ifstream::binary);
  std::stringstream buffer;
  buffer << in.rdbuf();
  return buffer.str();
}

time_t FileUtils::getModifiedTime(const std::string& file) {
  struct stat attrib;
  if (::stat(file.c_str(), &attrib) == 0) {
    return attrib.st_mtime;
  }

  PLOG(ERROR) << "Unable to get file modified time for " << file;
  return SP_NOTOK;
}

bool FileUtils::is_symlink(const std::string& filepath) {
  struct stat attrib;
  if (::lstat(filepath.c_str(), &attrib) == 0) {
    return S_ISLNK(attrib.st_mode);
  }

  PLOG(ERROR) << "Unable to check if file is a symlink " << filepath;
  return false;
}

bool FileUtils::writeAll(const std::string& filename, const char* data, size_t len) {
  std::ofstream ot(filename.c_str(), std::ios::out | std::ios::binary);
  if (!ot) return false;
  ot.write(reinterpret_cast<const char*>(data), len);
  ot.close();
  return true;
}

sp_int32 FileUtils::getCwd(std::string& path) {
  char maxpath[MAXPATHLEN];
  if (::getcwd(maxpath, MAXPATHLEN) == nullptr) {
    PLOG(ERROR) << "Could not get the current working directory";
    return SP_NOTOK;
  }

  path = maxpath;
  return SP_OK;
}
