// 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 <utility>
#include <vector>

#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;
  }
  if (type != net::WebSocketFrameHeader::kOpCodeContinuation) {
    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;
}

void CobaltWebSocketEventHandler::OnWriteDone(uint64_t bytes_written) {
  creator_->OnWriteDone(bytes_written);
}

void CobaltWebSocketEventHandler::OnFlowControl(int64_t quota) {
  creator_->OnFlowControl(quota);
}

}  // namespace websocket
}  // namespace cobalt
