// Copyright (c) 2012 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 "net/quic/quic_protocol.h"
#include "base/stl_util.h"

using base::StringPiece;
using std::map;
using std::numeric_limits;
using std::ostream;

namespace net {

QuicStreamFrame::QuicStreamFrame() {}

QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
                                 bool fin,
                                 uint64 offset,
                                 StringPiece data)
    : stream_id(stream_id),
      fin(fin),
      offset(offset),
      data(data) {
}

// TODO(ianswett): Initializing largest_received to 0 should not be necessary.
ReceivedPacketInfo::ReceivedPacketInfo() : largest_received(0) {}

ReceivedPacketInfo::~ReceivedPacketInfo() {}

void ReceivedPacketInfo::RecordReceived(
    QuicPacketSequenceNumber sequence_number) {
  DCHECK(IsAwaitingPacket(sequence_number));
  if (largest_received < sequence_number) {
    DCHECK_LT(sequence_number - largest_received,
              numeric_limits<uint16>::max());
    // We've got a new high sequence number.  Note any new intermediate missing
    // packets, and update the last_ack data.
    for (QuicPacketSequenceNumber i = largest_received + 1;
         i < sequence_number; ++i) {
      DVLOG(1) << "missing " << i;
      missing_packets.insert(i);
    }
    largest_received = sequence_number;
  } else {
    // We've gotten one of the out of order packets - remove it from our
    // "missing packets" list.
    DVLOG(1) << "Removing "  << sequence_number << " from missing list";
    missing_packets.erase(sequence_number);
  }
}

bool ReceivedPacketInfo::IsAwaitingPacket(
    QuicPacketSequenceNumber sequence_number) const {
  return sequence_number > largest_received ||
      ContainsKey(missing_packets, sequence_number);
}

void ReceivedPacketInfo::ClearMissingBefore(
    QuicPacketSequenceNumber least_unacked) {
  missing_packets.erase(missing_packets.begin(),
                        missing_packets.lower_bound(least_unacked));
}

SentPacketInfo::SentPacketInfo() {}

SentPacketInfo::~SentPacketInfo() {}

// Testing convenience method.
QuicAckFrame::QuicAckFrame(QuicPacketSequenceNumber largest_received,
                           QuicPacketSequenceNumber least_unacked) {
  for (QuicPacketSequenceNumber seq_num = 1;
       seq_num <= largest_received; ++seq_num) {
    received_info.RecordReceived(seq_num);
  }
  received_info.largest_received = largest_received;
  sent_info.least_unacked = least_unacked;
}

ostream& operator<<(ostream& os, const SentPacketInfo& s) {
  os << "least_waiting: " << s.least_unacked;
  return os;
}

ostream& operator<<(ostream& os, const ReceivedPacketInfo& r) {
  os << "largest_received: "
     << r.largest_received
     << " missing_packets: [ ";
  for (SequenceSet::const_iterator it = r.missing_packets.begin();
       it != r.missing_packets.end(); ++it) {
    os << *it << " ";
  }
  return os;
}

QuicCongestionFeedbackFrame::QuicCongestionFeedbackFrame() {
}

QuicCongestionFeedbackFrame::~QuicCongestionFeedbackFrame() {
}

ostream& operator<<(ostream& os, const QuicCongestionFeedbackFrame& c) {
  os << "type: " << c.type;
  switch (c.type) {
    case kInterArrival: {
      const CongestionFeedbackMessageInterArrival& inter_arrival =
          c.inter_arrival;
      os << " accumulated_number_of_lost_packets: "
         << inter_arrival.accumulated_number_of_lost_packets;
      os << " offset_time: " << inter_arrival.offset_time;
      os << " delta_time: " << inter_arrival.delta_time;
      os << " received packets: [ ";
      for (TimeMap::const_iterator it =
               inter_arrival.received_packet_times.begin();
           it != inter_arrival.received_packet_times.end(); ++it) {
        os << it->first << "@" << it->second.ToMilliseconds() << " ";
      }
      os << "]";
      break;
    }
    case kFixRate: {
      os << " bitrate_in_bytes_per_second: "
         << c.fix_rate.bitrate_in_bytes_per_second;
      break;
    }
    case kTCP: {
      const CongestionFeedbackMessageTCP& tcp = c.tcp;
      os << " accumulated_number_of_lost_packets: "
         << c.tcp.accumulated_number_of_lost_packets;
      os << " receive_window: " << tcp.receive_window;
      break;
    }
    default: {
      DLOG(FATAL) << "Unsupported congestion info type: "
                  << c.type;
    }
  }
 return os;
}

ostream& operator<<(ostream& os, const QuicAckFrame& a) {
  os << "sent info { " << a.sent_info << " } "
     << "received info { " << a.received_info << " }\n";
 return os;
}

CongestionFeedbackMessageInterArrival::
CongestionFeedbackMessageInterArrival() {}

CongestionFeedbackMessageInterArrival::
~CongestionFeedbackMessageInterArrival() {}

QuicFecData::QuicFecData() {}

bool QuicFecData::operator==(const QuicFecData& other) const {
  if (fec_group != other.fec_group) {
    return false;
  }
  if (min_protected_packet_sequence_number !=
      other.min_protected_packet_sequence_number) {
    return false;
  }
  if (redundancy != other.redundancy) {
    return false;
  }
  return true;
}

QuicData::~QuicData() {
  if (owns_buffer_) {
    delete [] const_cast<char*>(buffer_);
  }
}

}  // namespace net
