// 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.
#ifndef COBALT_WEBSOCKET_WEB_SOCKET_FRAME_CONTAINER_H_
#define COBALT_WEBSOCKET_WEB_SOCKET_FRAME_CONTAINER_H_

#include <algorithm>
#include <deque>

#include "base/basictypes.h"
#include "net/base/io_buffer.h"
#include "net/websockets/websocket_frame.h"

namespace cobalt {
namespace websocket {

const size_t kMaxFramePayloadInBytes = 4 * 1024 * 1024;

class WebSocketFrameContainer {
 public:
  typedef std::deque<const net::WebSocketFrameChunk*> WebSocketFrameChunks;
  typedef WebSocketFrameChunks::iterator iterator;
  typedef WebSocketFrameChunks::const_iterator const_iterator;

  WebSocketFrameContainer()
      : frame_completed_(false),
        payload_size_bytes_(0),
        expected_payload_size_bytes_(0) {}
  ~WebSocketFrameContainer() { clear(); }

  void clear();

  const net::WebSocketFrameHeader* GetHeader() const {
    if (empty()) {
      return NULL;
    }

    return (*begin())->header.get();
  }

  bool IsControlFrame() const;
  bool IsDataFrame() const;
  bool IsContinuationFrame() const;

  enum ErrorCode {
    kErrorNone,
    kErrorMaxFrameSizeViolation,
    kErrorFirstChunkMissingHeader,
    kErrorHasExtraHeader,
    kErrorFrameAlreadyComplete,
    kErrorPayloadSizeSmallerThanHeader,
    kErrorPayloadSizeLargerThanHeader
  };

  bool IsFrameComplete() const { return frame_completed_; }

  bool IsFinalFrame() const {
    const net::WebSocketFrameHeader* const header = GetHeader();
    if (!header) {
      return false;
    }
    return (header && header->final);
  }

  // Note that this takes always ownership of the chunk.
  // Should only be called if IsFrameComplete() is false.
  // Note that if there is an error produced in the function, it will
  // leave the state of this object unchanged.
  ErrorCode Take(const net::WebSocketFrameChunk* chunk);

  iterator begin() { return chunks_.begin(); }
  iterator end() { return chunks_.end(); }
  const_iterator begin() const { return chunks_.begin(); }
  const_iterator end() const { return chunks_.end(); }
  const_iterator cbegin() const { return chunks_.begin(); }
  const_iterator cend() const { return chunks_.end(); }
  bool empty() const { return begin() == end(); }

  std::size_t GetCurrentPayloadSizeBytes() const { return payload_size_bytes_; }
  std::size_t GetChunkCount() const { return chunks_.size(); }

  void swap(WebSocketFrameContainer& other) {
    std::swap(frame_completed_, other.frame_completed_);
    std::swap(payload_size_bytes_, other.payload_size_bytes_);
    std::swap(expected_payload_size_bytes_, other.expected_payload_size_bytes_);
    chunks_.swap(other.chunks_);
  }

  // Returns false if op_code was not found, and returns true otherwise.
  bool GetFrameOpCode(net::WebSocketFrameHeader::OpCode* op_code) const {
    DCHECK(op_code);
    if (empty()) {
      return false;
    }

    const net::WebSocketFrameChunk* first_chunk(*begin());
    DCHECK(first_chunk);
    const scoped_ptr<net::WebSocketFrameHeader>& first_chunk_header =
        first_chunk->header;
    if (!first_chunk_header) {
      NOTREACHED() << "No header found in the first chunk.";
      return false;
    }

    *op_code = first_chunk_header->opcode;
    return true;
  }

 private:
  // Note: If you add a field, please remember to update swap() above.
  bool frame_completed_;
  std::size_t payload_size_bytes_;
  std::size_t expected_payload_size_bytes_;
  WebSocketFrameChunks chunks_;
};

}  // namespace websocket
}  // namespace cobalt

#endif  // COBALT_WEBSOCKET_WEB_SOCKET_FRAME_CONTAINER_H_
