// Copyright 2014 The Chromium 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 <cstdio>
#include <cstdlib>
#include <deque>
#include <string>
#include <utility>

#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/cast/test/utility/udp_proxy.h"
#include "net/base/ip_address.h"
#include "starboard/string.h"
#include "starboard/types.h"

class ByteCounter {
 public:
  ByteCounter() : bytes_(0), packets_(0) { push(base::TimeTicks::Now()); }

  base::TimeDelta time_range() {
    return time_data_.back() - time_data_.front();
  }

  void push(base::TimeTicks now) {
    byte_data_.push_back(bytes_);
    packet_data_.push_back(packets_);
    time_data_.push_back(now);
    while (time_range().InSeconds() > 10) {
      byte_data_.pop_front();
      packet_data_.pop_front();
      time_data_.pop_front();
    }
  }

  double megabits_per_second() {
    double megabits = (byte_data_.back() - byte_data_.front()) * 8 / 1E6;
    return megabits / time_range().InSecondsF();
  }

  double packets_per_second() {
    double packets = packet_data_.back() - packet_data_.front();
    return packets / time_range().InSecondsF();
  }

  void Increment(uint64_t x) {
    bytes_ += x;
    packets_++;
  }

 private:
  uint64_t bytes_;
  uint64_t packets_;
  std::deque<uint64_t> byte_data_;
  std::deque<uint64_t> packet_data_;
  std::deque<base::TimeTicks> time_data_;
};

namespace {
struct GlobalCounter {
  base::TimeTicks last_printout;
  ByteCounter in_pipe_input_counter;
  ByteCounter in_pipe_output_counter;
  ByteCounter out_pipe_input_counter;
  ByteCounter out_pipe_output_counter;
};
}  // namespace

base::LazyInstance<GlobalCounter>::Leaky g_counter = LAZY_INSTANCE_INITIALIZER;

class ByteCounterPipe : public media::cast::test::PacketPipe {
 public:
  explicit ByteCounterPipe(ByteCounter* counter) : counter_(counter) {}
  void Send(std::unique_ptr<media::cast::Packet> packet) final {
    counter_->Increment(packet->size());
    pipe_->Send(std::move(packet));
  }

 private:
  ByteCounter* counter_;
};

void SetupByteCounters(std::unique_ptr<media::cast::test::PacketPipe>* pipe,
                       ByteCounter* pipe_input_counter,
                       ByteCounter* pipe_output_counter) {
  media::cast::test::PacketPipe* new_pipe =
      new ByteCounterPipe(pipe_input_counter);
  new_pipe->AppendToPipe(std::move(*pipe));
  new_pipe->AppendToPipe(std::unique_ptr<media::cast::test::PacketPipe>(
      new ByteCounterPipe(pipe_output_counter)));
  pipe->reset(new_pipe);
}

void CheckByteCounters() {
  base::TimeTicks now = base::TimeTicks::Now();
  g_counter.Get().in_pipe_input_counter.push(now);
  g_counter.Get().in_pipe_output_counter.push(now);
  g_counter.Get().out_pipe_input_counter.push(now);
  g_counter.Get().out_pipe_output_counter.push(now);
  if ((now - g_counter.Get().last_printout).InSeconds() >= 5) {
    fprintf(stderr, "Sending  : %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
            g_counter.Get().in_pipe_output_counter.megabits_per_second(),
            g_counter.Get().in_pipe_input_counter.megabits_per_second(),
            g_counter.Get().in_pipe_output_counter.packets_per_second(),
            g_counter.Get().in_pipe_input_counter.packets_per_second());
    fprintf(stderr, "Receiving: %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
            g_counter.Get().out_pipe_output_counter.megabits_per_second(),
            g_counter.Get().out_pipe_input_counter.megabits_per_second(),
            g_counter.Get().out_pipe_output_counter.packets_per_second(),
            g_counter.Get().out_pipe_input_counter.packets_per_second());

    g_counter.Get().last_printout = now;
  }
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, base::Bind(&CheckByteCounters),
      base::TimeDelta::FromMilliseconds(100));
}

int main(int argc, char** argv) {
  base::AtExitManager at_exit;
  base::CommandLine::Init(argc, argv);
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  InitLogging(settings);

  if (argc != 5 && argc != 3) {
    fprintf(stderr,
            "Usage: udp_proxy <localport> <remotehost> <remoteport> <type>\n"
            "or:\n"
            "       udp_proxy <localport> <type>\n"
            "Where type is one of: perfect, wifi, bad, evil, poisson-wifi\n");
    exit(1);
  }

  net::IPAddress remote_ip_address;
  std::string network_type;
  int local_port = SbStringAToI(argv[1]);
  int remote_port = 0;

  if (argc == 5) {
    // V2 proxy
    CHECK(remote_ip_address.AssignFromIPLiteral(argv[2]));
    remote_port = SbStringAToI(argv[3]);
    network_type = argv[4];
  } else {
    // V1 proxy
    network_type = argv[2];
  }
  if (local_port < 0 || local_port > 65535 || remote_port < 0 ||
      remote_port > 65535) {
    fprintf(stderr, "Port numbers must be between 0 and 65535\n");
    exit(1);
  }
  net::IPEndPoint remote_endpoint(remote_ip_address,
                                  static_cast<uint16_t>(remote_port));
  net::IPEndPoint local_endpoint(net::IPAddress::IPv4AllZeros(),
                                 static_cast<uint16_t>(local_port));
  std::unique_ptr<media::cast::test::PacketPipe> in_pipe, out_pipe;
  std::unique_ptr<media::cast::test::InterruptedPoissonProcess> ipp(
      media::cast::test::DefaultInterruptedPoissonProcess());

  if (network_type == "perfect") {
    // No action needed.
  } else if (network_type == "wifi") {
    in_pipe = media::cast::test::WifiNetwork();
    out_pipe = media::cast::test::WifiNetwork();
  } else if (network_type == "bad") {
    in_pipe = media::cast::test::BadNetwork();
    out_pipe = media::cast::test::BadNetwork();
  } else if (network_type == "evil") {
    in_pipe = media::cast::test::EvilNetwork();
    out_pipe = media::cast::test::EvilNetwork();
  } else if (network_type == "poisson-wifi") {
    in_pipe = ipp->NewBuffer(128 * 1024);
    out_pipe = ipp->NewBuffer(128 * 1024);
  } else {
    fprintf(stderr, "Unknown network type.\n");
    exit(1);
  }

  SetupByteCounters(&in_pipe, &(g_counter.Get().in_pipe_input_counter),
                    &(g_counter.Get().in_pipe_output_counter));
  SetupByteCounters(&out_pipe, &(g_counter.Get().out_pipe_input_counter),
                    &(g_counter.Get().out_pipe_output_counter));

  printf("Press Ctrl-C when done.\n");
  std::unique_ptr<media::cast::test::UDPProxy> proxy(
      media::cast::test::UDPProxy::Create(local_endpoint, remote_endpoint,
                                          std::move(in_pipe),
                                          std::move(out_pipe), NULL));
  base::MessageLoop message_loop;
  g_counter.Get().last_printout = base::TimeTicks::Now();
  CheckByteCounters();
  base::RunLoop().Run();
  return 1;
}
