// Copyright 2014 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.

#include "sync/internal_api/public/attachments/attachment_downloader_impl.h"

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_fetcher.h"
#include "sync/internal_api/public/attachments/attachment_uploader_impl.h"
#include "sync/protocol/sync.pb.h"
#include "url/gurl.h"

namespace syncer {

struct AttachmentDownloaderImpl::DownloadState {
 public:
  DownloadState(const AttachmentId& attachment_id,
                const AttachmentUrl& attachment_url);

  AttachmentId attachment_id;
  AttachmentUrl attachment_url;
  // |access_token| needed to invalidate if downloading attachment fails with
  // HTTP_UNAUTHORIZED.
  std::string access_token;
  scoped_ptr<net::URLFetcher> url_fetcher;
  std::vector<DownloadCallback> user_callbacks;
};

AttachmentDownloaderImpl::DownloadState::DownloadState(
    const AttachmentId& attachment_id,
    const AttachmentUrl& attachment_url)
    : attachment_id(attachment_id), attachment_url(attachment_url) {
}

AttachmentDownloaderImpl::AttachmentDownloaderImpl(
    const GURL& sync_service_url,
    const scoped_refptr<net::URLRequestContextGetter>&
        url_request_context_getter,
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes,
    const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
        token_service_provider)
    : OAuth2TokenService::Consumer("attachment-downloader-impl"),
      sync_service_url_(sync_service_url),
      url_request_context_getter_(url_request_context_getter),
      account_id_(account_id),
      oauth2_scopes_(scopes),
      token_service_provider_(token_service_provider) {
  DCHECK(!account_id.empty());
  DCHECK(!scopes.empty());
  DCHECK(token_service_provider_.get());
  DCHECK(url_request_context_getter_.get());
}

AttachmentDownloaderImpl::~AttachmentDownloaderImpl() {
}

void AttachmentDownloaderImpl::DownloadAttachment(
    const AttachmentId& attachment_id,
    const DownloadCallback& callback) {
  DCHECK(CalledOnValidThread());

  AttachmentUrl url = AttachmentUploaderImpl::GetURLForAttachmentId(
                          sync_service_url_, attachment_id).spec();

  StateMap::iterator iter = state_map_.find(url);
  if (iter == state_map_.end()) {
    // There is no request started for this attachment id. Let's create
    // DownloadState and request access token for it.
    scoped_ptr<DownloadState> new_download_state(
        new DownloadState(attachment_id, url));
    iter = state_map_.add(url, new_download_state.Pass()).first;
    RequestAccessToken(iter->second);
  }
  DownloadState* download_state = iter->second;
  DCHECK(download_state->attachment_id == attachment_id);
  download_state->user_callbacks.push_back(callback);
}

void AttachmentDownloaderImpl::OnGetTokenSuccess(
    const OAuth2TokenService::Request* request,
    const std::string& access_token,
    const base::Time& expiration_time) {
  DCHECK(CalledOnValidThread());
  DCHECK(request == access_token_request_.get());
  access_token_request_.reset();
  StateList::const_iterator iter;
  // Start downloads for all download requests waiting for access token.
  for (iter = requests_waiting_for_access_token_.begin();
       iter != requests_waiting_for_access_token_.end();
       ++iter) {
    DownloadState* download_state = *iter;
    download_state->access_token = access_token;
    download_state->url_fetcher =
        CreateFetcher(download_state->attachment_url, access_token).Pass();
    download_state->url_fetcher->Start();
  }
  requests_waiting_for_access_token_.clear();
}

void AttachmentDownloaderImpl::OnGetTokenFailure(
    const OAuth2TokenService::Request* request,
    const GoogleServiceAuthError& error) {
  DCHECK(CalledOnValidThread());
  DCHECK(request == access_token_request_.get());
  access_token_request_.reset();
  StateList::const_iterator iter;
  // Without access token all downloads fail.
  for (iter = requests_waiting_for_access_token_.begin();
       iter != requests_waiting_for_access_token_.end();
       ++iter) {
    DownloadState* download_state = *iter;
    scoped_refptr<base::RefCountedString> null_attachment_data;
    ReportResult(
        *download_state, DOWNLOAD_UNSPECIFIED_ERROR, null_attachment_data);
    DCHECK(state_map_.find(download_state->attachment_url) != state_map_.end());
    state_map_.erase(download_state->attachment_url);
  }
  requests_waiting_for_access_token_.clear();
}

void AttachmentDownloaderImpl::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK(CalledOnValidThread());

  // Find DownloadState by url.
  AttachmentUrl url = source->GetOriginalURL().spec();
  StateMap::iterator iter = state_map_.find(url);
  DCHECK(iter != state_map_.end());
  const DownloadState& download_state = *iter->second;
  DCHECK(source == download_state.url_fetcher.get());

  DownloadResult result = DOWNLOAD_UNSPECIFIED_ERROR;
  scoped_refptr<base::RefCountedString> attachment_data;

  if (source->GetResponseCode() == net::HTTP_OK) {
    result = DOWNLOAD_SUCCESS;
    std::string data_as_string;
    source->GetResponseAsString(&data_as_string);
    attachment_data = base::RefCountedString::TakeString(&data_as_string);
  } else if (source->GetResponseCode() == net::HTTP_UNAUTHORIZED) {
    OAuth2TokenServiceRequest::InvalidateToken(token_service_provider_.get(),
                                               account_id_,
                                               oauth2_scopes_,
                                               download_state.access_token);
    // TODO(pavely): crbug/380437. This is transient error. Request new access
    // token for this DownloadState. The only trick is to do it with exponential
    // backoff.
  }
  ReportResult(download_state, result, attachment_data);
  state_map_.erase(iter);
}

scoped_ptr<net::URLFetcher> AttachmentDownloaderImpl::CreateFetcher(
    const AttachmentUrl& url,
    const std::string& access_token) {
  scoped_ptr<net::URLFetcher> url_fetcher(
      net::URLFetcher::Create(GURL(url), net::URLFetcher::GET, this));
  const std::string auth_header("Authorization: Bearer " + access_token);
  url_fetcher->AddExtraRequestHeader(auth_header);
  url_fetcher->SetRequestContext(url_request_context_getter_.get());
  url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
                            net::LOAD_DO_NOT_SEND_COOKIES |
                            net::LOAD_DISABLE_CACHE);
  // TODO(maniscalco): Set an appropriate headers (User-Agent, what else?) on
  // the request (bug 371521).
  return url_fetcher.Pass();
}

void AttachmentDownloaderImpl::RequestAccessToken(
    DownloadState* download_state) {
  requests_waiting_for_access_token_.push_back(download_state);
  // Start access token request if there is no active one.
  if (access_token_request_ == NULL) {
    access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart(
        token_service_provider_.get(), account_id_, oauth2_scopes_, this);
  }
}

void AttachmentDownloaderImpl::ReportResult(
    const DownloadState& download_state,
    const DownloadResult& result,
    const scoped_refptr<base::RefCountedString>& attachment_data) {
  std::vector<DownloadCallback>::const_iterator iter;
  for (iter = download_state.user_callbacks.begin();
       iter != download_state.user_callbacks.end();
       ++iter) {
    scoped_ptr<Attachment> attachment;
    if (result == DOWNLOAD_SUCCESS) {
      attachment.reset(new Attachment(Attachment::CreateWithId(
          download_state.attachment_id, attachment_data)));
    }

    base::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(*iter, result, base::Passed(&attachment)));
  }
}

}  // namespace syncer
