/**
 * @file ArchiveMetadata.cpp
 * ArchiveMetadata class definition
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 "ArchiveMetadata.h"

#include <archive.h>
#include <archive_entry.h>

#include <list>
#include <string>
#include <algorithm>
#include <iostream>

#include "utils/file/FileManager.h"
#include "utils/gsl.h"
#include "Exception.h"

using org::apache::nifi::minifi::Exception;
using org::apache::nifi::minifi::ExceptionType;

rapidjson::Value ArchiveEntryMetadata::toJson(rapidjson::Document::AllocatorType &alloc) const {
    rapidjson::Value entryVal(rapidjson::kObjectType);

    rapidjson::Value entryNameVal;
    entryNameVal.SetString(entryName.c_str(), gsl::narrow<rapidjson::SizeType>(entryName.length()));
    entryVal.AddMember("entry_name", entryNameVal, alloc);

    entryVal.AddMember("entry_type", entryType, alloc);
    entryVal.AddMember("entry_perm", entryPerm, alloc);
    entryVal.AddMember("entry_size", entrySize, alloc);
    entryVal.AddMember("entry_uid", entryUID, alloc);
    entryVal.AddMember("entry_gid", entryGID, alloc);
    entryVal.AddMember("entry_mtime", entryMTime, alloc);
    entryVal.AddMember("entry_mtime_nsec", entryMTimeNsec, alloc);

    if (entryType == AE_IFREG) {
        rapidjson::Value stashKeyVal;
        stashKeyVal.SetString(stashKey.c_str(), gsl::narrow<rapidjson::SizeType>(stashKey.length()));
        entryVal.AddMember("stash_key", stashKeyVal, alloc);
    }

    return entryVal;
}

void ArchiveEntryMetadata::loadJson(const rapidjson::Value& entryVal) {
    entryName.assign(entryVal["entry_name"].GetString());
    entryType = gsl::narrow<mode_t>(entryVal["entry_type"].GetUint64());
    entryPerm = gsl::narrow<mode_t>(entryVal["entry_perm"].GetUint64());
    entrySize = entryVal["entry_size"].GetUint64();
    entryUID = gsl::narrow<uid_t>(entryVal["entry_uid"].GetUint64());
    entryGID = entryVal["entry_gid"].GetUint64();
    entryMTime = entryVal["entry_mtime"].GetUint64();
    entryMTimeNsec = entryVal["entry_mtime_nsec"].GetInt64();

    if (entryType == AE_IFREG)
        stashKey.assign(entryVal["stash_key"].GetString());
}

ArchiveEntryMetadata ArchiveEntryMetadata::fromJson(const rapidjson::Value& entryVal) {
    ArchiveEntryMetadata aem;
    aem.loadJson(entryVal);
    return aem;
}

ArchiveEntryIterator ArchiveMetadata::find(const std::string& name) {
    auto targetTest = [&](const ArchiveEntryMetadata& entry) -> bool {
        return entry.entryName == name;
    };

    return std::find_if(entryMetadata.begin(),
                        entryMetadata.end(),
                        targetTest);
}

ArchiveEntryIterator ArchiveMetadata::eraseEntry(ArchiveEntryIterator position) {
    return entryMetadata.erase(position);
}

ArchiveEntryIterator ArchiveMetadata::insertEntry(
    ArchiveEntryIterator position, const ArchiveEntryMetadata& entry) {
    return entryMetadata.insert(position, entry);
}

rapidjson::Value ArchiveMetadata::toJson(rapidjson::Document::AllocatorType &alloc) const {
    rapidjson::Value structVal(rapidjson::kArrayType);

    for (const auto &entry : entryMetadata) {
        structVal.PushBack(entry.toJson(alloc), alloc);
    }

    rapidjson::Value lensVal(rapidjson::kObjectType);

    rapidjson::Value archiveFormatNameVal;
    archiveFormatNameVal.SetString(archiveFormatName.c_str(), gsl::narrow<rapidjson::SizeType>(archiveFormatName.length()));
    lensVal.AddMember("archive_format_name", archiveFormatNameVal, alloc);

    lensVal.AddMember("archive_format", archiveFormat, alloc);
    lensVal.AddMember("archive_structure", structVal, alloc);

    if (!archiveName.empty()) {
        rapidjson::Value archiveNameVal;
        archiveNameVal.SetString(archiveName.c_str(), gsl::narrow<rapidjson::SizeType>(archiveName.length()));
        lensVal.AddMember("archive_name", archiveNameVal, alloc);
    }

   rapidjson::Value focusedEntryVal;
    focusedEntryVal.SetString(focusedEntry.c_str(), gsl::narrow<rapidjson::SizeType>(focusedEntry.length()));
    lensVal.AddMember("focused_entry", focusedEntryVal, alloc);

    return lensVal;
}

ArchiveMetadata ArchiveMetadata::fromJson(const rapidjson::Value& metadataDoc) {
    ArchiveMetadata am;
    am.loadJson(metadataDoc);
    return am;
}

void ArchiveMetadata::loadJson(const rapidjson::Value& metadataDoc) {
    rapidjson::Value::ConstMemberIterator itr = metadataDoc.FindMember("archive_name");
    if (itr != metadataDoc.MemberEnd())
        archiveName.assign(itr->value.GetString());

    archiveFormatName.assign(metadataDoc["archive_format_name"].GetString());
    archiveFormat = gsl::narrow<int>(metadataDoc["archive_format"].GetUint64());

    focusedEntry = metadataDoc["focused_entry"].GetString();
  
    for (const auto &entryVal : metadataDoc["archive_structure"].GetArray()) {
        entryMetadata.push_back(ArchiveEntryMetadata::fromJson(entryVal));
    }
}

void ArchiveMetadata::seedTempPaths(fileutils::FileManager *file_man, bool keep = false) {
    for (auto& entry : entryMetadata)
        entry.tmpFileName.assign(file_man->unique_file(keep));
}

ArchiveStack ArchiveStack::fromJson(const rapidjson::Value& input) {
    ArchiveStack as;
    as.loadJson(input);
    return as;
}

ArchiveStack ArchiveStack::fromJsonString(const std::string& input) {
    ArchiveStack as;
    as.loadJsonString(input);
    return as;
}

void ArchiveStack::loadJson(const rapidjson::Value& lensStack) {
    for (const auto& metadata : lensStack.GetArray()) {
        stack_.push_back(ArchiveMetadata::fromJson(metadata));
    }
}

void ArchiveStack::loadJsonString(const std::string& input) {
    rapidjson::Document lensStack;
    rapidjson::ParseResult ok = lensStack.Parse(input.c_str());

    if (!ok) {
        std::stringstream ss;
        ss << "Failed to parse archive lens stack from JSON string with reason: "
           << rapidjson::GetParseError_En(ok.Code())
           << " at offset " << ok.Offset();

        throw Exception(ExceptionType::GENERAL_EXCEPTION, ss.str());
    }

    loadJson(lensStack);
}

rapidjson::Document ArchiveStack::toJson() const {
    rapidjson::Document lensStack(rapidjson::kArrayType);
    rapidjson::Document::AllocatorType &alloc = lensStack.GetAllocator();

    for (const auto& metadata : stack_) {
        lensStack.PushBack(metadata.toJson(alloc), alloc);
    }

    return lensStack;
}

std::string ArchiveStack::toJsonString() const {
    rapidjson::Document d = toJson();

    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    d.Accept(writer);
    
    std::string jsonString = buffer.GetString();
    return jsonString;
}
