/*
 * Copyright (C) 2012 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 <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include "Log.h"
#include "Settings.h"
#include "StringUtil.h"
#include "FileUtil.h"


// This class is used by Log. So we cannot use LOG? macros here.
#define _LOGD_(x...) do { fprintf(stderr, x); fprintf(stderr, "\n"); } while(0)

// reported generated under reports/YYYY_MM_DD_HH_MM_SS dir
const char reportTopDir[] = "reports";
android::String8 FileUtil::mDirPath;

bool FileUtil::prepare(android::String8& dirPath)
{
    if (mDirPath.length() != 0) {
        dirPath = mDirPath;
        _LOGD_("mDirPath %s", mDirPath.string());
        return true;
    }

    time_t timeNow = time(NULL);
    if (timeNow == ((time_t)-1)) {
        _LOGD_("time error");
       return false;
    }
    // tm is allocated in static buffer, and should not be freed.
    struct tm* tm = localtime(&timeNow);
    if (tm == NULL) {
        _LOGD_("localtime error");
        return false;
    }
    int result = mkdir(reportTopDir, S_IRWXU);
    if ((result == -1) && (errno != EEXIST)) {
        _LOGD_("mkdir of topdir failed, error %d", errno);
        return false;
    }
    android::String8 reportTime;
    if (reportTime.appendFormat("%04d_%02d_%02d_%02d_%02d_%02d", tm->tm_year + 1900,
                tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec) != 0) {
            return false;
    }
    Settings::Instance()->addSetting(Settings::EREPORT_TIME, reportTime);
    android::String8 path;
    if (path.appendFormat("%s/%s", reportTopDir, reportTime.string()) != 0) {
        return false;
    }
    result = mkdir(path.string(), S_IRWXU);
    if ((result == -1) && (errno != EEXIST)) {
        _LOGD_("mkdir of report dir failed, error %d", errno);
        return false;
    }
    mDirPath = path;
    dirPath = path;

    return true;
}

FileUtil::FileUtil()
{
    mBuffer = new char[DEFAULT_BUFFER_SIZE];
    if (mBuffer == NULL) {
        // cannot use ASSERT here, just crash
        abort();
    }
    mBufferSize = DEFAULT_BUFFER_SIZE;
}

FileUtil::~FileUtil()
{
    if (mFile.is_open()) {
        mFile.close();
    }
    delete[] mBuffer;
}

bool FileUtil::init(const char* fileName)
{
    if (fileName == NULL) {
        return true;
    }

    mFile.open(fileName, std::ios::out | std::ios::trunc);
    if (!mFile.is_open()) {
            return false;
        }
    return true;
}

bool FileUtil::doVprintf(bool fileOnly, int logLevel, const char *fmt, va_list ap)
{
    // prevent messed up log in multi-thread env. Still multi-line logs can be messed up.
    android::Mutex::Autolock lock(mWriteLock);
    while (1) {
        int start = 0;
        if (logLevel != -1) {
            mBuffer[0] = '0' + logLevel;
            mBuffer[1] = '>';
            start = 2;
        }
        int size;
        size = vsnprintf(mBuffer + start, mBufferSize - start - 2, fmt, ap); // 2 for \n\0
        if (size < 0) {
            fprintf(stderr, "FileUtil::vprintf failed");
            return false;
        }
        if ((size + start + 2) > mBufferSize) {
            //default buffer does not fit, increase buffer size and retry
            delete[] mBuffer;
            mBuffer = new char[2 * size];
            if (mBuffer == NULL) {
                // cannot use ASSERT here, just crash
                abort();
            }
            mBufferSize = 2 * size;
            // re-try
            continue;
        }
        size += start;
        mBuffer[size] = '\n';
        size++;
        mBuffer[size] = 0;

        if (!fileOnly) {
            fprintf(stdout, "%s", mBuffer);
        }
        if (mFile.is_open()) {
            mFile<<mBuffer;
        }
        return true;
    }
}

bool FileUtil::doPrintf(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    bool result = doVprintf(false, -1, fmt, ap);
    va_end(ap);
    return result;
}
