// 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 <memory>
#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) {
      memcpy(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 occurred, 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
