/*
 * Copyright 2024 Bloomberg Finance LP
 *
 * 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 <buildboxcommontest_utils.h>

using namespace buildboxcommon;

namespace buildboxcommontest {

DirectoryNodeFactory::DirectoryNodeFactory(const std::string &name,
                                           const DirectoryFactory &directory)
    : d_name(name)
{
    d_directory = std::make_shared<DirectoryFactory>(directory);
}

DirectoryNode DirectoryNodeFactory::create(DirectoryTree &outputTree) const
{
    DirectoryNode node;
    node.set_name(d_name);
    Directory dir = d_directory->create(outputTree);
    outputTree.root = DigestGenerator::hash(dir);
    node.mutable_digest()->CopyFrom(outputTree.root);
    return node;
}

DirectoryFactory::DirectoryFactory(
    const std::vector<FileNodeFactory> &files,
    const std::vector<DirectoryNodeFactory> &directories,
    const std::vector<SymlinkNodeFactory> &symlinks,
    const std::map<std::string, std::string> &properties,
    std::optional<mode_t> mode)
    : d_files(files), d_directories(directories), d_symlinks(symlinks),
      d_properties(properties), d_mode(mode)
{
    std::sort(
        d_files.begin(), d_files.end(),
        [](const auto &f1, const auto &f2) { return f1.d_name < f2.d_name; });
    std::sort(
        d_directories.begin(), d_directories.end(),
        [](const auto &f1, const auto &f2) { return f1.d_name < f2.d_name; });
    std::sort(
        d_symlinks.begin(), d_symlinks.end(),
        [](const auto &f1, const auto &f2) { return f1.d_name < f2.d_name; });
}

Directory DirectoryFactory::create(DirectoryTree &outputTree) const
{
    Directory dir;
    for (const auto &f : d_files) {
        FileNode *fileNode = dir.add_files();
        fileNode->CopyFrom(f.create());
    }
    for (const auto &s : d_symlinks) {
        SymlinkNode *symlinkNode = dir.add_symlinks();
        symlinkNode->CopyFrom(s.create());
    }
    for (const auto &d : d_directories) {
        DirectoryNode *dirNode = dir.add_directories();
        dirNode->CopyFrom(d.create(outputTree));
    }
    for (const auto &it : d_properties) {
        auto nodeProperty = dir.mutable_node_properties()->add_properties();
        nodeProperty->set_name(it.first);
        nodeProperty->set_value(it.second);
    }
    if (d_mode.has_value()) {
        dir.mutable_node_properties()->mutable_unix_mode()->set_value(
            d_mode.value());
    }
    outputTree.root = DigestGenerator::hash(dir);
    outputTree.map.emplace(outputTree.root, dir);
    return dir;
}

} // namespace buildboxcommontest
