#include "fullarc_toolkit.h"

#include <saas/rtyserver/components/fullarchive/globals.h>
#include <kernel/multipart_archive/abstract/globals.h>

#include <util/folder/filelist.h>
#include <util/stream/file.h>
#include <util/string/cast.h>

static const TStringBuf OriginPrefix("ORIGIN:");

bool IsFullArcPartFile(const TString& fileName) {
    // check [indexfullarc.]full.part.123
    if (!fileName.StartsWith(FULL_ARC_FILE_NAME_PREFIX)) {
        return false;
    }
    // check indexfullarc.full[.part.]123
    size_t partExtPos = fileName.find(NRTYArchive::PART_EXT);
    if (partExtPos == TString::npos) {
        return false;
    }
    // check indexfullarc.full.part.[123]
    TString partNumber(fileName.data() + partExtPos + NRTYArchive::PART_EXT.length());
    ui32 tmp;
    if (!TryFromString<ui32>(partNumber, tmp)) {
        return false;
    }
    return true;
}

void CreateFakeFullArcParts(const TFsPath& indexDir) {
    // DATALESS part implementation doesn't use contents of the part file. However it copies the file correctly during
    // the merge of FullArc archives. We rely on this behavior to keep track of file copying: original name is
    // preserved inside the part file. After the merge, contents of part files are analyzed to restore the mapping
    // between source and destination index segments and apply similar rename commands to real parts afterwards.
    try {
        TDirsList segmentsList;
        segmentsList.Fill(indexDir);
        while (TString segment = segmentsList.Next()) {
            TFileList partHeaders;
            partHeaders.Fill(indexDir / segment, FULL_ARC_FILE_NAME_PREFIX, NRTYArchive::PART_HEADER_EXT, true);
            while (TString partHeader = partHeaders.Next()) {
                Y_ASSERT(partHeader.EndsWith(NRTYArchive::PART_HEADER_EXT));
                TStringBuf partName(partHeader.data(), partHeader.length() - NRTYArchive::PART_HEADER_EXT.length());
                TUnbufferedFileOutput partFile(indexDir / segment / partName);
                partFile << OriginPrefix << (TFsPath(segment) / partName);
            }
        }
    } catch(yexception& e) {
        e << " in CreateFakeFullArcParts('" << indexDir << "')";
        throw;
    }
}

TString GetFullArcPartOrigin(const TFsPath& partPath) {
    TUnbufferedFileInput partFile(partPath);
    TString line;
    partFile >> line;
    Y_VERIFY(line.StartsWith(OriginPrefix));
    return TString(line.data() + OriginPrefix.length());
}
