/*
 * Copyright 2022 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_BUILDBOXCASD_LOCALACPROXYINSTANCE_H
#define INCLUDED_BUILDBOXCASD_LOCALACPROXYINSTANCE_H

#include <buildboxcasd_acinstance.h>
#include <buildboxcasd_actionstorage.h>
#include <buildboxcasd_casinstance.h>
#include <buildboxcasd_digestcache.h>
#include <buildboxcasd_localacinstance.h>
#include <buildboxcommon_connectionoptions.h>
#include <buildboxcommon_remoteexecutionclient.h>

using namespace build::bazel::remote::execution::v2;

using grpc::Status;

namespace buildboxcasd {

class LocalAcProxyInstance final : public AcInstance {
    /* This class implements an ActionCache server that also
     * acts as a proxy pointing to a remote cache.
     *
     * Inheriting from `AcInstance` ensures consistent usage
     */
  public:
    explicit LocalAcProxyInstance(
        const std::shared_ptr<ActionStorage> &storage,
        const std::shared_ptr<CasInstance> &cas, bool readOnly,
        const buildboxcommon::ConnectionOptions &ac_endpoint,
        const bool read_only_remote = false, const int validationCacheTtl = 0);

    LocalAcProxyInstance(const LocalAcProxyInstance &other,
                         std::shared_ptr<CasInstance> cas, bool readOnly)
        : AcInstance(other.d_storage, cas, other.isReadOnly() || readOnly),
          d_ac_client(other.d_ac_client),
          d_local_instance(other.d_local_instance),
          d_remote_instance_name(other.d_remote_instance_name),
          d_read_only_remote(other.d_read_only_remote) {};
    std::shared_ptr<AcInstance> clone(std::shared_ptr<CasInstance> cas,
                                      bool readOnly) override;

    // Implements virtual functions from the ACInstance interface
    grpc::Status GetActionResult(const GetActionResultRequest &request,
                                 ActionResult *result) override;
    grpc::Status UpdateActionResult(const UpdateActionResultRequest &request,
                                    ActionResult *result) override;

  private:
    std::shared_ptr<buildboxcommon::RemoteExecutionClient> d_ac_client;
    std::shared_ptr<LocalAcInstance> d_local_instance;
    std::string d_remote_instance_name;
    bool d_read_only_remote = false;
    // Cache digests of action-result of which all referenced blobs exist
    std::optional<DigestCache> d_validationCache;
};

} // namespace buildboxcasd

#endif // INCLUDED_BUILDBOXCASD_LOCALACPROXYINSTANCE_H
