/*
 * Copyright (C) 2010 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.
 */

#define LOG_TAG "MtpUtils"

#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

#include "MtpUtils.h"

namespace android {

constexpr unsigned long FILE_COPY_SIZE = 262144;

/*
DateTime strings follow a compatible subset of the definition found in ISO 8601, and
take the form of a Unicode string formatted as: "YYYYMMDDThhmmss.s". In this
representation, YYYY shall be replaced by the year, MM replaced by the month (01-12),
DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date,
hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the
second (00-59). The ".s" is optional, and represents tenths of a second.
This is followed by a UTC offset given as "[+-]zzzz" or the literal "Z", meaning UTC.
*/

bool parseDateTime(const char* dateTime, time_t& outSeconds) {
    int year, month, day, hour, minute, second;
    if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d",
               &year, &month, &day, &hour, &minute, &second) != 6)
        return false;

    // skip optional tenth of second
    const char* tail = dateTime + 15;
    if (tail[0] == '.' && tail[1]) tail += 2;

    // FIXME: "Z" means UTC, but non-"Z" doesn't mean local time.
    // It might be that you're in Asia/Seoul on vacation and your Android
    // device has noticed this via the network, but your camera was set to
    // America/Los_Angeles once when you bought it and doesn't know where
    // it is right now, so the camera says "20160106T081700-0800" but we
    // just ignore the "-0800" and assume local time which is actually "+0900".
    // I think to support this (without switching to Java or using icu4c)
    // you'd want to always use timegm(3) and then manually add/subtract
    // the UTC offset parsed from the string (taking care of wrapping).
    // mktime(3) ignores the tm_gmtoff field, so you can't let it do the work.
    bool useUTC = (tail[0] == 'Z');

    struct tm tm = {};
    tm.tm_sec = second;
    tm.tm_min = minute;
    tm.tm_hour = hour;
    tm.tm_mday = day;
    tm.tm_mon = month - 1;  // mktime uses months in 0 - 11 range
    tm.tm_year = year - 1900;
    tm.tm_isdst = -1;
    outSeconds = useUTC ? timegm(&tm) : mktime(&tm);

    return true;
}

void formatDateTime(time_t seconds, char* buffer, int bufferLength) {
    struct tm tm;

    localtime_r(&seconds, &tm);
    snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d",
        tm.tm_year + 1900,
        tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
        tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
}

int copyFile(const char *fromPath, const char *toPath) {
    auto start = std::chrono::steady_clock::now();

    android::base::unique_fd fromFd(open(fromPath, O_RDONLY));
    if (fromFd == -1) {
        PLOG(ERROR) << "Failed to open copy from " << fromPath;
        return -1;
    }
    android::base::unique_fd toFd(open(toPath, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR));
    if (toFd == -1) {
        PLOG(ERROR) << "Failed to open copy to " << toPath;
        return -1;
    }
    off_t offset = 0;

    struct stat sstat = {};
    if (stat(fromPath, &sstat) == -1)
        return -1;

    off_t length = sstat.st_size;
    int ret = 0;

    while (offset < length) {
        ssize_t transfer_length = std::min(length - offset, (off_t) FILE_COPY_SIZE);
        ret = sendfile(toFd, fromFd, &offset, transfer_length);
        if (ret != transfer_length) {
            ret = -1;
            PLOG(ERROR) << "Copying failed!";
            break;
        }
    }
    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double> diff = end - start;
    LOG(INFO) << "Copied a file with MTP. Time: " << diff.count() << " s, Size: " << length <<
        ", Rate: " << ((double) length) / diff.count() << " bytes/s";
    return ret == -1 ? -1 : 0;
}

void deleteRecursive(const char* path) {
    char pathbuf[PATH_MAX];
    size_t pathLength = strlen(path);
    if (pathLength >= sizeof(pathbuf) - 1) {
        LOG(ERROR) << "path too long: " << path;
    }
    strcpy(pathbuf, path);
    if (pathbuf[pathLength - 1] != '/') {
        pathbuf[pathLength++] = '/';
    }
    char* fileSpot = pathbuf + pathLength;
    int pathRemaining = sizeof(pathbuf) - pathLength - 1;

    DIR* dir = opendir(path);
    if (!dir) {
        PLOG(ERROR) << "opendir " << path << " failed";
        return;
    }

    struct dirent* entry;
    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;

        // ignore "." and ".."
        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
            continue;
        }

        int nameLength = strlen(name);
        if (nameLength > pathRemaining) {
            LOG(ERROR) << "path " << path << "/" << name << " too long";
            continue;
        }
        strcpy(fileSpot, name);

        if (entry->d_type == DT_DIR) {
            deleteRecursive(pathbuf);
            rmdir(pathbuf);
        } else {
            unlink(pathbuf);
        }
    }
    closedir(dir);
}

void deletePath(const char* path) {
    struct stat statbuf;
    if (stat(path, &statbuf) == 0) {
        if (S_ISDIR(statbuf.st_mode)) {
            deleteRecursive(path);
            rmdir(path);
        } else {
            unlink(path);
        }
    } else {
        PLOG(ERROR) << "deletePath stat failed for " << path;;
    }
}

}  // namespace android
