// Copyright 2018 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/cobalt_web_socket_event_handler.h"

#include "base/logging.h"
#include "cobalt/websocket/web_socket_impl.h"

namespace cobalt {
namespace websocket {
namespace {
typedef std::vector<std::pair<scoped_refptr<net::IOBuffer>, size_t>>
    FrameDataVector;
std::size_t GetMessageLength(const FrameDataVector& frame_data) {
  std::size_t total_length = 0;
  for (const auto& i : frame_data) {
    total_length += i.second;
  }
  return total_length;
}
std::size_t CombineFramesChunks(FrameDataVector::const_iterator begin,
                                FrameDataVector::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 (FrameDataVector::const_iterator iterator = begin; iterator != end;
       ++iterator) {
    const scoped_refptr<net::IOBuffer>& data = iterator->first;

    std::size_t frame_chunk_size = iterator->second;

    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_EQ(bytes_written, buffer_length);
  return bytes_written;
}
}  // namespace

void CobaltWebSocketEventHandler::OnAddChannelResponse(
    const std::string& selected_subprotocol,
    const std::string& /*extensions*/) {
  creator_->OnHandshakeComplete(selected_subprotocol);
}
void CobaltWebSocketEventHandler::OnDataFrame(
    bool fin, WebSocketMessageType type, scoped_refptr<net::IOBuffer> buffer,
    size_t buffer_size) {
  if (message_type_ == net::WebSocketFrameHeader::kOpCodeControlUnused) {
    message_type_ = type;
  }
  DCHECK_EQ(message_type_, type);
  frame_data_.push_back(std::make_pair(std::move(buffer), buffer_size));
  if (fin) {
    std::size_t message_length = GetMessageLength(frame_data_);
    scoped_refptr<net::IOBufferWithSize> buf =
        base::WrapRefCounted(new net::IOBufferWithSize(message_length));
    CombineFramesChunks(frame_data_.begin(), frame_data_.end(), buf->data(),
                        message_length);
    frame_data_.clear();

    bool is_text_message =
        message_type_ == net::WebSocketFrameHeader::kOpCodeText;
    if (is_text_message && buf && (buf->size() > 0)) {
      base::StringPiece payload_string_piece(buf->data(), buf->size());
      if (!base::IsStringUTF8(payload_string_piece)) {
        WebSocketImpl::CloseInfo close_info(net::kWebSocketErrorProtocolError);
        creator_->TrampolineClose(close_info);
        return;
      }
    }
    creator_->OnWebSocketReceivedData(is_text_message, std::move(buf));
  }
}

void CobaltWebSocketEventHandler::OnClosingHandshake() {
  creator_->OnClose(true, net::kWebSocketNormalClosure,
                    "Received close handshake initiation.");
}

void CobaltWebSocketEventHandler::OnFailChannel(const std::string& message) {
  DLOG(WARNING) << "WebSocket channel failed due to: " << message;
  creator_->OnClose(true, net::kWebSocketErrorAbnormalClosure, message);
}


void CobaltWebSocketEventHandler::OnDropChannel(bool was_clean, uint16_t code,
                                                const std::string& reason) {
  creator_->OnClose(was_clean, code, reason);
}

void CobaltWebSocketEventHandler::OnSSLCertificateError(
    std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
        ssl_error_callbacks,
    const GURL& /*url*/, const net::SSLInfo& /*ssl_info*/, bool /*fatal*/) {
  // TODO: determine if there are circumstances we want to continue
  // the request.
  DLOG(WARNING) << "SSL cert failure occured, cancelling connection";
  ssl_error_callbacks->CancelSSLRequest(net::ERR_BAD_SSL_CLIENT_AUTH_CERT,
                                        nullptr);
}
int CobaltWebSocketEventHandler::OnAuthRequired(
    scoped_refptr<net::AuthChallengeInfo> /*auth_info*/,
    scoped_refptr<net::HttpResponseHeaders> /*response_headers*/,
    const net::HostPortPair& /*host_port_pair*/,
    base::OnceCallback<void(const net::AuthCredentials*)> /*callback*/,
    base::Optional<net::AuthCredentials>* /*credentials*/) {
  NOTIMPLEMENTED();
  return net::OK;
}

}  // namespace websocket
}  // namespace cobalt