/*
 * Copyright 2021 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.
 */

#ifndef INCLUDED_BUILDBOXRUN_CONTAINER_HOST
#define INCLUDED_BUILDBOXRUN_CONTAINER_HOST

#include <memory>

#include <buildboxcommon_casclient.h>
#include <buildboxcommon_localcasstageddirectory.h>
#include <buildboxcommon_temporarydirectory.h>

#include <buildboxrun_oci.h>

namespace buildboxcommon {
namespace buildboxrun {
namespace oci {

class OCIRunner::ContainerHost {
  public:
    ContainerHost(OCIRunner *r, const Command &cmdValue,
                  const Digest &workdirDigest,
                  const std::shared_ptr<CASClient> &casClient,
                  StageTreeRequest_StagingMode stagingMode);

    // default destructor
    ~ContainerHost() = default;

    ContainerHost(const ContainerHost &) = delete;
    ContainerHost &operator=(const ContainerHost &) = delete;
    ContainerHost(ContainerHost &&) = delete;
    ContainerHost &operator=(ContainerHost &&) = delete;

    ActionResult execute();

    /* For all output paths in the command, stage the directories leading up to
     * the output path in the bundle's filesystem. */
    void prepareFilesystem() const;

  private:
    /* Generates and stages a config.json spec file for the bundle,
     * incorporating information from the Command we have received. */
    void stageSpec() const;
    /* Executes the command. Mutates "result" so it contains the result of the
     * execution. */
    ActionResult executeCommand();

    /* A pointer to the runner that this host is bound to. */
    OCIRunner *d_runner;
    /* The work directory, which contains the bundle spec file and the
     * filesystem. */
    LocalCasStagedDirectory d_workdir;
    /* The path of d_workdir. */
    const std::filesystem::path d_workdirPath;
    /* The command to be executed. Since this class is always initialized as a
     * variable inside OCIRunner, this pointer shouldn't be dangling. */
    const Command &d_cmd;
};
} // namespace oci
} // namespace buildboxrun
} // namespace buildboxcommon

#endif
