// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "codec_runner.h"

#include <lib/async/cpp/task.h>
#include <lib/fidl/cpp/clone.h>

namespace codec_runner {

CodecRunner::CodecRunner(async_dispatcher_t* fidl_dispatcher,
                         thrd_t fidl_thread)
    : fidl_dispatcher_(fidl_dispatcher), fidl_thread_(fidl_thread) {
  // nothing else to do here
}

CodecRunner::~CodecRunner() = default;

void CodecRunner::BindAndOwnSelf(
    fidl::InterfaceRequest<fuchsia::media::StreamProcessor> codec_request,
    std::unique_ptr<CodecRunner> self) {
  assert(thrd_current() == fidl_thread_);
  // We have input_constraints_ by now thanks to our behavior (server-side),
  // so this can be an assert().
  assert(input_constraints_);

  binding_ = std::make_unique<BindingType>(std::move(self));
  binding_->set_error_handler([this](zx_status_t error) {
    // No point in trying to send an epitaph here since the reason we're here
    // is the other end being gone.
    //
    // This class is only used for running one Codec instance per process.
    //
    // Since the channel failed, the client probably won't see this message.
    Exit("The Codec channel failed server-side.  Normal if client is done.");
  });
  binding_->Bind(std::move(codec_request), fidl_dispatcher_);

  // Some sub-classes already want to convey some output constraints as early
  // as possible - this is a place for those sub-classes to do so.  Sending
  // before input constraints encourages the client to configure output before
  // delivering input that starts the first stream, to try to avoid extra
  // output re-configs.
  onInputConstraintsReady();

  // Now we can tell the client about the input constraints.  We do this as an
  // event because the client has no choice re. whether the client needs
  // these. These are _always_ needed by the client.  Also, as an event it
  // would be easier to have the CodecFactory potentially send these instead
  // of the Codec to save a bit on latency.
  //
  // Intentional copy, in case a derived class wants to refer to
  // input_constraints_.
  //
  // TODO(dustingreen): Make these serial, make the serial context be the same
  // one and be visible to all the places that need to send, probably serial
  // context in CodecRunner as a protected field.  OR, ask and confirm that
  // async::PostTask() is guaranteed to remain serial (like it was before, and
  // like it seems to be the vast majority of the time currently).
  input_constraints_sent_ = true;

  // We post here so that we're ordered after similar posting done in
  // onInputConstraintsReady() above, so that the derived class has every chance
  // to send output constraints before input constraints to encourage client to
  // configure output before starting to deliver input data.
  async::PostTask(fidl_dispatcher_, [this] {
    binding_->events().OnInputConstraints(fidl::Clone(*input_constraints_));
  });

  onSetupDone();
}

void CodecRunner::Exit(const char* format, ...) {
  // TODO(dustingreen): Send epitaph when possible.

  // Let's not have a buffer on the stack, not because it couldn't be done
  // safely, but because we'd potentially run into stack size vs. message length
  // tradeoffs, stack expansion granularity fun, or whatever else.

  va_list args;
  va_start(args, format);
  size_t buffer_bytes = vsnprintf(nullptr, 0, format, args) + 1;
  va_end(args);

  // ~buffer never actually runs since this method never returns
  std::unique_ptr<char[]> buffer(new char[buffer_bytes]);

  va_start(args, format);
  size_t buffer_bytes_2 =
      vsnprintf(buffer.get(), buffer_bytes, format, args) + 1;
  (void)buffer_bytes_2;
  // sanity check; should match so go ahead and assert that it does.
  assert(buffer_bytes == buffer_bytes_2);
  va_end(args);

  // TODO(dustingreen): It might be worth wiring this up to the log in a more
  // official way, especially if doing so would print a timestamp automatically
  // and/or provide filtering goodness etc.
  printf("%s  --  Codec server isolate will exit(-1)\n", buffer.get());

  // TODO(dustingreen): Send string in buffer via epitaph, when possible.  First
  // we should switch to events so we'll only have the Codec channel not the
  // CodecEvents channel. Note to self: The channel failing server-side may race
  // with trying to send.

  // TODO(dustingreen): determine if our heap leak detection will be able to
  // tolerate this exit(-1) and still detect leaks - and fix it to tolerate if
  // it doesn't already, because it should.

  exit(-1);
}

}  // namespace codec_runner
