// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// An implementation of WebSocketStreamHandle.

#include "webkit/glue/websocketstreamhandle_impl.h"

#include <vector>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSocketStreamHandleClient.h"
#include "webkit/glue/websocketstreamhandle_bridge.h"
#include "webkit/glue/websocketstreamhandle_delegate.h"

namespace webkit_glue {

// WebSocketStreamHandleImpl::Context -----------------------------------------

class WebSocketStreamHandleImpl::Context
    : public base::RefCounted<Context>,
      public WebSocketStreamHandleDelegate {
 public:
  explicit Context(WebSocketStreamHandleImpl* handle);

  WebKit::WebSocketStreamHandleClient* client() const { return client_; }
  void set_client(WebKit::WebSocketStreamHandleClient* client) {
    client_ = client;
  }

  void Connect(const WebKit::WebURL& url);
  bool Send(const WebKit::WebData& data);
  void Close();

  // Must be called before |handle_| or |client_| is deleted.
  // Once detached, it never calls |client_| back.
  void Detach();

  // WebSocketStreamHandleDelegate methods:
  virtual void DidOpenStream(WebKit::WebSocketStreamHandle*, int);
  virtual void DidSendData(WebKit::WebSocketStreamHandle*, int);
  virtual void DidReceiveData(
      WebKit::WebSocketStreamHandle*, const char*, int);
  virtual void DidClose(WebKit::WebSocketStreamHandle*);

 private:
  friend class base::RefCounted<Context>;
  ~Context() {
    DCHECK(!handle_);
    DCHECK(!client_);
    DCHECK(!bridge_);
  }

  WebSocketStreamHandleImpl* handle_;
  WebKit::WebSocketStreamHandleClient* client_;
  // |bridge_| is alive from Connect to DidClose, so Context must be alive
  // in the time period.
  scoped_refptr<WebSocketStreamHandleBridge> bridge_;

  DISALLOW_COPY_AND_ASSIGN(Context);
};

WebSocketStreamHandleImpl::Context::Context(WebSocketStreamHandleImpl* handle)
    : handle_(handle),
      client_(NULL),
      bridge_(NULL) {
}

void WebSocketStreamHandleImpl::Context::Connect(const WebKit::WebURL& url) {
  VLOG(1) << "Connect url=" << url;
  DCHECK(!bridge_);
  bridge_ = WebSocketStreamHandleBridge::Create(handle_, this);
  AddRef();  // Will be released by DidClose().
  bridge_->Connect(url);
}

bool WebSocketStreamHandleImpl::Context::Send(const WebKit::WebData& data) {
  VLOG(1) << "Send data.size=" << data.size();
  DCHECK(bridge_);
  return bridge_->Send(
      std::vector<char>(data.data(), data.data() + data.size()));
}

void WebSocketStreamHandleImpl::Context::Close() {
  VLOG(1) << "Close";
  if (bridge_)
    bridge_->Close();
}

void WebSocketStreamHandleImpl::Context::Detach() {
  handle_ = NULL;
  client_ = NULL;
  // If Connect was called, |bridge_| is not NULL, so that this Context closes
  // the |bridge_| here.  Then |bridge_| will call back DidClose, and will
  // be released by itself.
  // Otherwise, |bridge_| is NULL.
  if (bridge_)
    bridge_->Close();
}

void WebSocketStreamHandleImpl::Context::DidOpenStream(
    WebKit::WebSocketStreamHandle* web_handle, int max_amount_send_allowed) {
  VLOG(1) << "DidOpen";
  if (client_)
    client_->didOpenStream(handle_, max_amount_send_allowed);
}

void WebSocketStreamHandleImpl::Context::DidSendData(
    WebKit::WebSocketStreamHandle* web_handle, int amount_sent) {
  if (client_)
    client_->didSendData(handle_, amount_sent);
}

void WebSocketStreamHandleImpl::Context::DidReceiveData(
    WebKit::WebSocketStreamHandle* web_handle, const char* data, int size) {
  if (client_)
    client_->didReceiveData(handle_, WebKit::WebData(data, size));
}

void WebSocketStreamHandleImpl::Context::DidClose(
    WebKit::WebSocketStreamHandle* web_handle) {
  VLOG(1) << "DidClose";
  bridge_ = NULL;
  WebSocketStreamHandleImpl* handle = handle_;
  handle_ = NULL;
  if (client_) {
    WebKit::WebSocketStreamHandleClient* client = client_;
    client_ = NULL;
    client->didClose(handle);
  }
  Release();
}

// WebSocketStreamHandleImpl ------------------------------------------------

WebSocketStreamHandleImpl::WebSocketStreamHandleImpl()
    : ALLOW_THIS_IN_INITIALIZER_LIST(context_(new Context(this))) {
}

WebSocketStreamHandleImpl::~WebSocketStreamHandleImpl() {
  // We won't receive any events from |context_|.
  // |context_| is ref counted, and will be released when it received
  // DidClose.
  context_->Detach();
}

void WebSocketStreamHandleImpl::connect(
    const WebKit::WebURL& url, WebKit::WebSocketStreamHandleClient* client) {
  VLOG(1) << "connect url=" << url;
  DCHECK(!context_->client());
  context_->set_client(client);

  context_->Connect(url);
}

bool WebSocketStreamHandleImpl::send(const WebKit::WebData& data) {
  return context_->Send(data);
}

void WebSocketStreamHandleImpl::close() {
  context_->Close();
}

}  // namespace webkit_glue
