/*
 * Copyright 2012 Google Inc. 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 "net/dial/dial_service.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/string_piece.h"
#include "base/stringprintf.h"
#include "net/base/net_errors.h"
#include "net/server/http_server_request_info.h"
#include "net/url_request/url_request.h"

namespace net {

namespace {
const char* kUdpServerAgent = "Cobalt/2.0 UPnP/1.1";
}  // namespace

DialService::DialService() {
  http_server_ = new DialHttpServer(this);
  udp_server_.reset(new DialUdpServer(http_server_->location_url(),
                                      kUdpServerAgent));

  // Compute HTTP local address and cache it.
  IPEndPoint addr;
  if (http_server_->GetLocalAddress(&addr) == net::OK) {
    http_host_address_ = addr.ToString();
  } else {
    DLOG(WARNING) << "Could not start Dial Server";
  }
}

DialService::~DialService() {
  DCHECK(thread_checker_.CalledOnValidThread());
  Terminate();
}

const std::string& DialService::http_host_address() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return http_host_address_;
}

void DialService::Terminate() {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Note that we may not have the last ref to http_server_, so we can't control
  // where it gets destroyed. Ensure we stop it on the right thread.
  if (http_server_) {
    http_server_->Stop();
  }
  http_server_ = NULL;
  udp_server_.reset();
}

void DialService::Register(const scoped_refptr<DialServiceHandler>& handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  TRACE_EVENT0("net::dial", __FUNCTION__);
  DCHECK(handler);
  const std::string& path = handler->service_name();
  if (!path.empty()) {
    handlers_[path] = handler;
  }
}

void DialService::Deregister(const scoped_refptr<DialServiceHandler>& handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  TRACE_EVENT0("net::dial", __FUNCTION__);
  DCHECK(handler);
  for (ServiceHandlerMap::iterator it = handlers_.begin();
      it != handlers_.end(); ++it) {
    if (it->second == handler) {
      handlers_.erase(it);
      break;
    }
  }
}

scoped_refptr<DialServiceHandler> DialService::GetHandler(
    const std::string& request_path,
    std::string* handler_path) {
  // This function should only be called by DialHttpServer, to find a handler
  // to respond to an incoming request.
  DCHECK(thread_checker_.CalledOnValidThread());

  DCHECK(handler_path != NULL);
  TRACE_EVENT0("net::dial", __FUNCTION__);

  VLOG(1) << "Requesting Handler for path: " << request_path;
  base::StringPiece path(request_path);

  // remove '/apps/'
  const base::StringPiece kUrlPrefix("/apps/");
  if (!path.starts_with(kUrlPrefix)) {
    return NULL;
  }
  path = path.substr(kUrlPrefix.size());

  // find the next '/', and extract the portion in between.
  size_t pos = path.find_first_of('/');
  std::string service_path = path.substr(0, pos).as_string();

  // sanity check further, then extract the data.
  DCHECK_EQ(std::string::npos, service_path.find('/'));
  ServiceHandlerMap::const_iterator it = handlers_.find(service_path);
  if (it == handlers_.end()) {
    return NULL;
  }
  DCHECK(it->second);

  // for the remaining portion, extract it out as the handler path.
  *handler_path = path.substr(pos).as_string();

  // If the |handler_path| is empty, that means the request is "/apps/Foo", the
  // semantic equivalent of "/apps/Foo/". If we keep the |handler_path| empty,
  // somehow the JS does not catch it. So for now forcing it to "/" instead.
  if (handler_path->empty()) {
    *handler_path = std::string("/");
  }

  DCHECK_EQ('/', handler_path->at(0));

  return it->second;
}

DialServiceProxy::DialServiceProxy(
    const base::WeakPtr<DialService>& dial_service)
    : dial_service_(dial_service) {
  host_address_ = dial_service_->http_host_address();
  // Remember the message loop we were constructed on. We'll post all our tasks
  // there, to ensure thread safety when accessing dial_service_.
  message_loop_proxy_ = base::MessageLoopProxy::current();
}

DialServiceProxy::~DialServiceProxy() {}

void DialServiceProxy::Register(
    const scoped_refptr<DialServiceHandler>& handler) {
  message_loop_proxy_->PostTask(
      FROM_HERE, base::Bind(&DialServiceProxy::OnRegister, this, handler));
}

void DialServiceProxy::Deregister(
    const scoped_refptr<DialServiceHandler>& handler) {
  message_loop_proxy_->PostTask(
      FROM_HERE, base::Bind(&DialServiceProxy::OnDeregister, this, handler));
}

void DialServiceProxy::OnRegister(
    const scoped_refptr<DialServiceHandler>& handler) {
  if (dial_service_) {
    dial_service_->Register(handler);
  }
}

void DialServiceProxy::OnDeregister(
    const scoped_refptr<DialServiceHandler>& handler) {
  if (dial_service_) {
    dial_service_->Deregister(handler);
  }
}

}  // namespace net
