// 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_packet_creator.h"

#include "base/logging.h"
#include "net/quic/quic_utils.h"

using base::StringPiece;
using std::make_pair;
using std::min;
using std::pair;
using std::vector;

namespace net {

QuicPacketCreator::QuicPacketCreator(QuicGuid guid, QuicFramer* framer)
    : guid_(guid),
      framer_(framer),
      sequence_number_(0),
      fec_group_number_(1) {
  framer_->set_fec_builder(this);
}

QuicPacketCreator::~QuicPacketCreator() {
}

void QuicPacketCreator::OnBuiltFecProtectedPayload(
    const QuicPacketHeader& header,
    StringPiece payload) {
  if (fec_group_.get()) {
    fec_group_->Update(header, payload);
  }
}

size_t QuicPacketCreator::DataToStream(QuicStreamId id,
                                       StringPiece data,
                                       QuicStreamOffset offset,
                                       bool fin,
                                       vector<PacketPair>* packets) {
  DCHECK_GT(options_.max_packet_length,
            QuicUtils::StreamFramePacketOverhead(1));
  DCHECK_LT(0u, options_.max_num_packets);
  QuicPacketHeader header;

  QuicPacket* packet = NULL;
  QuicFrames frames;
  QuicFecGroupNumber current_fec_group = 0;
  QuicFecData fec_data;

  size_t num_data_packets = options_.max_num_packets;

  if (options_.use_fec) {
    DCHECK_LT(1u, options_.max_num_packets);
    --num_data_packets;
    DCHECK(!fec_group_.get());
    fec_group_.reset(new QuicFecGroup);
    current_fec_group = fec_group_number_;
    fec_data.fec_group = current_fec_group;
    fec_data.min_protected_packet_sequence_number = sequence_number_ + 1;
  }

  size_t unconsumed_bytes = data.size();
  if (data.size() != 0) {
    size_t max_frame_len = framer_->GetMaxPlaintextSize(
        options_.max_packet_length -
        QuicUtils::StreamFramePacketOverhead(1));
    DCHECK_GT(max_frame_len, 0u);
    size_t frame_len = min<size_t>(max_frame_len, unconsumed_bytes);

    while (unconsumed_bytes > 0 && num_data_packets > 0) {
      --num_data_packets;
      bool set_fin = false;
      if (unconsumed_bytes <= frame_len) {  // last loop
        frame_len = min(unconsumed_bytes, frame_len);
        set_fin = fin;
      }
      StringPiece data_frame(data.data() + data.size() - unconsumed_bytes,
                                frame_len);

      QuicStreamFrame frame(id, set_fin, offset, data_frame);
      frames.push_back(QuicFrame(&frame));
      FillPacketHeader(current_fec_group, PACKET_FLAGS_NONE, &header);
      offset += frame_len;
      unconsumed_bytes -= frame_len;

      // Produce the data packet (which might fin the stream).
      packet = framer_->ConstructFrameDataPacket(header, frames);
      DCHECK(packet);
      DCHECK_GE(options_.max_packet_length, packet->length());
      packets->push_back(make_pair(header.packet_sequence_number, packet));
      frames.clear();
    }
    // If we haven't finished serializing all the data, don't set any final fin.
    if (unconsumed_bytes > 0) {
      fin = false;
    }
  }

  // Create a new packet for the fin, if necessary.
  if (fin && data.size() == 0) {
    FillPacketHeader(current_fec_group, PACKET_FLAGS_NONE, &header);
    QuicStreamFrame frame(id, true, offset, "");
    frames.push_back(QuicFrame(&frame));
    packet = framer_->ConstructFrameDataPacket(header, frames);
    DCHECK(packet);
    packets->push_back(make_pair(header.packet_sequence_number, packet));
    frames.clear();
  }

  // Create a new FEC packet, if necessary
  if (current_fec_group != 0) {
    FillPacketHeader(current_fec_group, PACKET_FLAGS_FEC, &header);
    fec_data.redundancy = fec_group_->parity();
    QuicPacket* fec_packet = framer_->ConstructFecPacket(header, fec_data);
    DCHECK(fec_packet);
    packets->push_back(make_pair(header.packet_sequence_number, fec_packet));
    ++fec_group_number_;
  }
  /*
  if (options_.random_reorder) {
    int32 seed = ACMRandom::HostnamePidTimeSeed();
    ACMRandom random(seed);
    DLOG(INFO) << "Seed " << seed;

    vector<PacketPair> tmp_store;
    tmp_store.swap(*packets);

    while (tmp_store.size() != 0) {
      int idx = random.Uniform(tmp_store.size());
      packets->push_back(tmp_store[idx]);
      tmp_store.erase(tmp_store.begin() + idx);
    }
  }
  */
  fec_group_.reset(NULL);
  DCHECK(options_.max_num_packets >= packets->size());

  return data.size() - unconsumed_bytes;
}

QuicPacketCreator::PacketPair QuicPacketCreator::ResetStream(
    QuicStreamId id,
    QuicStreamOffset offset,
    QuicErrorCode error) {
  QuicPacketHeader header;
  FillPacketHeader(0, PACKET_FLAGS_NONE, &header);

  QuicRstStreamFrame close_frame(id, offset, error);

  QuicFrames frames;
  frames.push_back(QuicFrame(&close_frame));
  QuicPacket* packet = framer_->ConstructFrameDataPacket(header, frames);
  DCHECK(packet);
  return make_pair(header.packet_sequence_number, packet);
}

QuicPacketCreator::PacketPair QuicPacketCreator::CloseConnection(
    QuicConnectionCloseFrame* close_frame) {

  QuicPacketHeader header;
  FillPacketHeader(0, PACKET_FLAGS_NONE, &header);

  QuicFrames frames;
  frames.push_back(QuicFrame(close_frame));
  QuicPacket* packet = framer_->ConstructFrameDataPacket(header, frames);
  DCHECK(packet);
  return make_pair(header.packet_sequence_number, packet);
}

QuicPacketCreator::PacketPair QuicPacketCreator::AckPacket(
    QuicAckFrame* ack_frame) {

  QuicPacketHeader header;
  FillPacketHeader(0, PACKET_FLAGS_NONE, &header);

  QuicFrames frames;
  frames.push_back(QuicFrame(ack_frame));
  QuicPacket* packet = framer_->ConstructFrameDataPacket(header, frames);
  DCHECK(packet);
  return make_pair(header.packet_sequence_number, packet);
}

QuicPacketCreator::PacketPair QuicPacketCreator::CongestionFeedbackPacket(
    QuicCongestionFeedbackFrame* feedback_frame) {

  QuicPacketHeader header;
  FillPacketHeader(0, PACKET_FLAGS_NONE, &header);

  QuicFrames frames;
  frames.push_back(QuicFrame(feedback_frame));
  QuicPacket* packet = framer_->ConstructFrameDataPacket(header, frames);
  DCHECK(packet);
  return make_pair(header.packet_sequence_number, packet);
}

QuicPacketSequenceNumber QuicPacketCreator::SetNewSequenceNumber(
    QuicPacket* packet) {
  ++sequence_number_;
  framer_->WriteSequenceNumber(sequence_number_, packet);
  return sequence_number_;
}

void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
                                         QuicPacketFlags flags,
                                         QuicPacketHeader* header) {
  header->guid = guid_;
  header->flags = flags;
  header->packet_sequence_number = ++sequence_number_;
  header->fec_group = fec_group;
}

}  // namespace net
