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

#ifndef INCLUDED_BUILDBOXCOMMON_LOGSTREAMREADER
#define INCLUDED_BUILDBOXCOMMON_LOGSTREAMREADER

#include <buildboxcommon_connectionoptions.h>
#include <buildboxcommon_grpcclient.h>
#include <buildboxcommon_grpcretrier.h>
#include <buildboxcommon_logging.h>
#include <buildboxcommon_protos.h>

#include <chrono>
#include <memory>
#include <string>

namespace buildboxcommon {

class LogStreamReader final {

  public:
    LogStreamReader(std::string resourceName,
                    const ConnectionOptions &connectionOptions);

    LogStreamReader(std::string resourceName,
                    const std::shared_ptr<GrpcClient> &client);

    // Connect to another client
    void init(std::shared_ptr<google::bytestream::ByteStream::StubInterface>
                  bytestreamClient);

    // Issue a `ByteStream.Read()` for the given resource name, and return
    // whether the read was successful.
    //
    // The provided `onMessage` callback function is called for each chunk
    // of data received from the `ByteStream.Read()` request, to allow the
    // caller to define behaviour for handling the data in the LogStream.
    bool read(std::function<void(const std::string &)> onMessage,
              std::function<bool()> shouldStop);

    // Default implementation of `read` which prints the LogStream contents
    // to stdout.
    bool read();

    // The number of seconds to keep reading the stream after the operation
    // is done
    inline static std::chrono::seconds s_doneOpReadTimeout =
        std::chrono::seconds(
            10); // NOLINT (cppcoreguidelines-avoid-magic-numbers)

  private:
    std::string d_resourceName;
    std::shared_ptr<GrpcClient> d_grpcClient;
    std::shared_ptr<google::bytestream::ByteStream::StubInterface>
        d_byteStreamClient;
};

} // namespace buildboxcommon

#endif
