/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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 "util.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>


FileInfo::FileInfo()
{
    memset(this, 0, sizeof(FileInfo));
}

FileInfo::FileInfo(const FileInfo& that)
{
    memcpy(this, &that, sizeof(FileInfo));
}

FileInfo::FileInfo(const string& filename)
{
    struct stat st;
    int err = stat(filename.c_str(), &st);
    if (err != 0) {
        memset(this, 0, sizeof(FileInfo));
    } else {
        exists = true;
        mtime = st.st_mtime;
        ctime = st.st_ctime;
        size = st.st_size;
    }
}

bool
FileInfo::operator==(const FileInfo& that) const
{
    return exists == that.exists
            && mtime == that.mtime
            && ctime == that.ctime
            && size == that.size;
}

bool
FileInfo::operator!=(const FileInfo& that) const
{
    return exists != that.exists
            || mtime != that.mtime
            || ctime != that.ctime
            || size != that.size;
}

FileInfo::~FileInfo()
{
}

TrackedFile::TrackedFile()
    :filename(),
     fileInfo()
{
}

TrackedFile::TrackedFile(const TrackedFile& that)
{
    filename = that.filename;
    fileInfo = that.fileInfo;
}

TrackedFile::TrackedFile(const string& file)
    :filename(file),
     fileInfo(file)
{
}

TrackedFile::~TrackedFile()
{
}

bool
TrackedFile::HasChanged() const
{
    FileInfo updated(filename);
    return !updated.exists || fileInfo != updated;
}

void
get_directory_contents(const string& name, map<string,FileInfo>* results)
{
    DIR* dir = opendir(name.c_str());
    if (dir == NULL) {
        return;
    }

    dirent* entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        if (entry->d_type == DT_DIR) {
            string subdir = name + "/" + entry->d_name;
            get_directory_contents(subdir, results);
        } else if (entry->d_type == DT_LNK || entry->d_type == DT_REG) {
            string filename(name + "/" + entry->d_name);
            (*results)[filename] = FileInfo(filename);
        }
    }

    closedir(dir);
}

bool
directory_contents_differ(const map<string,FileInfo>& before, const map<string,FileInfo>& after)
{
    if (before.size() != after.size()) {
        return true;
    }
    map<string,FileInfo>::const_iterator b = before.begin();
    map<string,FileInfo>::const_iterator a = after.begin();
    while (b != before.end() && a != after.end()) {
        if (b->first != a->first) {
            return true;
        }
        if (a->second != b->second) {
            return true;
        }
        a++;
        b++;
    }
    return false;
}

string
escape_quotes(const char* str)
{
    string result;
    while (*str) {
        if (*str == '"') {
            result += '\\';
            result += '"';
        } else {
            result += *str;
        }
    }
    return result;
}

string
escape_for_commandline(const char* str)
{
    if (strchr(str, '"') != NULL || strchr(str, ' ') != NULL
            || strchr(str, '\t') != NULL) {
        return escape_quotes(str);
    } else {
        return str;
    }
}

static bool
spacechr(char c)
{
    return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}

string
trim(const string& str)
{
    const ssize_t N = (ssize_t)str.size();
    ssize_t begin = 0;
    while (begin < N && spacechr(str[begin])) {
        begin++;
    }
    ssize_t end = N - 1;
    while (end >= begin && spacechr(str[end])) {
        end--;
    }
    return string(str, begin, end-begin+1);
}

bool
starts_with(const string& str, const string& prefix)
{
    return str.compare(0, prefix.length(), prefix) == 0;
}

bool
ends_with(const string& str, const string& suffix)
{
    if (str.length() < suffix.length()) {
        return false;
    } else {
        return str.compare(str.length()-suffix.length(), suffix.length(), suffix) == 0;
    }
}

void
split_lines(vector<string>* result, const string& str)
{
    const int N = str.length();
    int begin = 0;
    int end = 0;
    for (; end < N; end++) {
        const char c = str[end];
        if (c == '\r' || c == '\n') {
            if (begin != end) {
                result->push_back(string(str, begin, end-begin));
            }
            begin = end+1;
        }
    }
    if (begin != end) {
        result->push_back(string(str, begin, end-begin));
    }
}

string
read_file(const string& filename)
{
    FILE* file = fopen(filename.c_str(), "r");
    if (file == NULL) {
        return string();
    }
    
    fseek(file, 0, SEEK_END);
    int size = ftell(file);
    fseek(file, 0, SEEK_SET);

    char* buf = (char*)malloc(size);
    if ((size_t) size != fread(buf, 1, size, file)) {
        free(buf);
        fclose(file);
        return string();
    }

    string result(buf, size);

    free(buf);
    fclose(file);

    return result;
}

bool
is_executable(const string& filename)
{
    int err;
    struct stat st;

    err = stat(filename.c_str(), &st);
    if (err != 0) {
        return false;
    }

    return (st.st_mode & S_IXUSR) != 0;
}

string
dirname(const string& filename)
{
    size_t slash = filename.rfind('/');
    if (slash == string::npos) {
        return "";
    } else if (slash == 0) {
        return "/";
    } else {
        return string(filename, 0, slash);
    }
}

string
leafname(const string& filename)
{
    size_t slash = filename.rfind('/');
    if (slash == string::npos) {
        return filename;
    } else if (slash == filename.length() - 1) {
        return "";
    } else {
        return string(filename, slash + 1);
    }
}
