// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include "cobalt/websocket/web_socket_message_container.h"

#include "base/basictypes.h"

namespace cobalt {
namespace websocket {

std::size_t CombineFramesChunks(WebSocketFrameContainer::const_iterator begin,
                                WebSocketFrameContainer::const_iterator end,
                                char *out_destination,
                                std::size_t buffer_length) {
  DCHECK(out_destination);
  std::size_t bytes_written = 0;
  std::size_t bytes_available = buffer_length;
  for (WebSocketFrameContainer::const_iterator iterator = begin;
       iterator != end; ++iterator) {
    const scoped_refptr<net::IOBufferWithSize> &data((*iterator)->data);

    if (data) {
      std::size_t frame_chunk_size = data->size();

      if (bytes_available >= frame_chunk_size) {
        SbMemoryCopy(out_destination, data->data(), frame_chunk_size);
        out_destination += frame_chunk_size;
        bytes_written += frame_chunk_size;
        bytes_available -= frame_chunk_size;
      }
    }
  }

  DCHECK_LE(bytes_written, buffer_length);
  return bytes_written;
}

bool WebSocketMessageContainer::Take(WebSocketFrameContainer *frame_container) {
  DCHECK(frame_container);
  DCHECK(!IsMessageComplete());
  DCHECK(frame_container->IsFrameComplete());
  if (!frame_container) {
    return false;
  }
  if (frame_container->empty()) {
    return true;
  }

  bool is_first_frame = frames_.empty();
  bool is_continuation_frame = frame_container->IsContinuationFrame();

  if (is_first_frame) {
    if (is_continuation_frame) {
      return false;
    }
  } else {
    // All frames after the first one must be continuation frames.
    if (!is_continuation_frame) {
      return false;
    }
  }

  frames_.push_back(WebSocketFrameContainer());

  WebSocketFrameContainer &last_object(frames_.back());
  last_object.swap(*frame_container);
  DCHECK(last_object.IsFrameComplete());

  payload_size_bytes_ += last_object.GetCurrentPayloadSizeBytes();
  message_completed_ |= last_object.IsFinalFrame();

  return true;
}

scoped_refptr<net::IOBufferWithSize>
WebSocketMessageContainer::GetMessageAsIOBuffer() const {
  scoped_refptr<net::IOBufferWithSize> buf;

  DCHECK_LE(kMaxMessagePayloadInBytes, static_cast<std::size_t>(kint32max));
  DCHECK_LE(payload_size_bytes_, kMaxMessagePayloadInBytes);
  DCHECK_GE(payload_size_bytes_, 0UL);

  if ((payload_size_bytes_ > 0) &&
      (payload_size_bytes_ <= kMaxMessagePayloadInBytes)) {
    buf = make_scoped_refptr(
        new net::IOBufferWithSize(static_cast<int>(payload_size_bytes_)));

    std::size_t total_bytes_written = 0;

    char *data_pointer = buf->data();
    std::size_t size_remaining = buf->size();

    for (WebSocketFrames::const_iterator iterator = frames_.begin();
         iterator != frames_.end(); ++iterator) {
      const WebSocketFrameContainer &frame_container(*iterator);

      std::size_t bytes_written =
          CombineFramesChunks(frame_container.begin(), frame_container.end(),
                              data_pointer, size_remaining);

      DCHECK_LE(bytes_written, size_remaining);

      size_remaining -= bytes_written;
      data_pointer += bytes_written;

      total_bytes_written += bytes_written;
    }

    DCHECK_EQ(total_bytes_written, payload_size_bytes_);
  }

  return buf;
}

}  // namespace websocket
}  // namespace cobalt
