// Copyright 2013 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 "chrome/browser/local_discovery/privet_http_impl.h"

#include <algorithm>
#include <vector>

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/local_discovery/privet_constants.h"
#include "components/cloud_devices/common/printer_description.h"
#include "net/base/url_util.h"
#include "printing/pwg_raster_settings.h"
#include "printing/units.h"
#include "ui/gfx/text_elider.h"
#include "url/gurl.h"

using namespace cloud_devices::printer;

namespace cloud_print {
extern const char kContentTypeJSON[];
}

namespace local_discovery {

namespace {
const char kUrlPlaceHolder[] = "http://host/";
const char kPrivetRegisterActionArgName[] = "action";
const char kPrivetRegisterUserArgName[] = "user";

const char kPrivetURLKeyUserName[] = "user_name";
const char kPrivetURLKeyClientName[] = "client_name";
const char kPrivetURLKeyJobname[] = "job_name";
const char kPrivetURLKeyOffline[] = "offline";
const char kPrivetURLValueOffline[] = "1";
const char kPrivetURLValueClientName[] = "Chrome";

const char kPrivetContentTypePDF[] = "application/pdf";
const char kPrivetContentTypePWGRaster[] = "image/pwg-raster";
const char kPrivetContentTypeAny[] = "*/*";

const char kPrivetStorageListPath[] = "/privet/storage/list";
const char kPrivetStorageContentPath[] = "/privet/storage/content";
const char kPrivetStorageParamPathFormat[] = "path=%s";

const char kPrivetKeyJobID[] = "job_id";

const int kPrivetCancelationTimeoutSeconds = 3;

const int kPrivetLocalPrintMaxRetries = 2;

const int kPrivetLocalPrintDefaultTimeout = 5;

const size_t kPrivetLocalPrintMaxJobNameLength = 64;

GURL CreatePrivetURL(const std::string& path) {
  GURL url(kUrlPlaceHolder);
  GURL::Replacements replacements;
  replacements.SetPathStr(path);
  return url.ReplaceComponents(replacements);
}

GURL CreatePrivetRegisterURL(const std::string& action,
                             const std::string& user) {
  GURL url = CreatePrivetURL(kPrivetRegisterPath);
  url = net::AppendQueryParameter(url, kPrivetRegisterActionArgName, action);
  return net::AppendQueryParameter(url, kPrivetRegisterUserArgName, user);
}

GURL CreatePrivetParamURL(const std::string& path,
                          const std::string& query_params) {
  GURL url(kUrlPlaceHolder);
  GURL::Replacements replacements;
  replacements.SetPathStr(path);
  if (!query_params.empty()) {
    replacements.SetQueryStr(query_params);
  }
  return url.ReplaceComponents(replacements);
}

}  // namespace

PrivetInfoOperationImpl::PrivetInfoOperationImpl(
    PrivetHTTPClient* privet_client,
    const PrivetJSONOperation::ResultCallback& callback)
    : privet_client_(privet_client), callback_(callback) {
}

PrivetInfoOperationImpl::~PrivetInfoOperationImpl() {
}

void PrivetInfoOperationImpl::Start() {
  url_fetcher_ = privet_client_->CreateURLFetcher(
      CreatePrivetURL(kPrivetInfoPath), net::URLFetcher::GET, this);

  url_fetcher_->DoNotRetryOnTransientError();
  url_fetcher_->SendEmptyPrivetToken();

  url_fetcher_->Start();
}

PrivetHTTPClient* PrivetInfoOperationImpl::GetHTTPClient() {
  return privet_client_;
}

void PrivetInfoOperationImpl::OnError(PrivetURLFetcher* fetcher,
                                      PrivetURLFetcher::ErrorType error) {
  callback_.Run(NULL);
}

void PrivetInfoOperationImpl::OnParsedJson(PrivetURLFetcher* fetcher,
                                           const base::DictionaryValue* value,
                                           bool has_error) {
  callback_.Run(value);
}

PrivetRegisterOperationImpl::PrivetRegisterOperationImpl(
    PrivetHTTPClient* privet_client,
    const std::string& user,
    PrivetRegisterOperation::Delegate* delegate)
    : user_(user),
      delegate_(delegate),
      privet_client_(privet_client),
      ongoing_(false) {
}

PrivetRegisterOperationImpl::~PrivetRegisterOperationImpl() {
}

void PrivetRegisterOperationImpl::Start() {
  ongoing_ = true;
  next_response_handler_ =
      base::Bind(&PrivetRegisterOperationImpl::StartResponse,
                 base::Unretained(this));
  SendRequest(kPrivetActionStart);
}

void PrivetRegisterOperationImpl::Cancel() {
  url_fetcher_.reset();

  if (ongoing_) {
    // Owned by the message loop.
    Cancelation* cancelation = new Cancelation(privet_client_, user_);

    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&PrivetRegisterOperationImpl::Cancelation::Cleanup,
                   base::Owned(cancelation)),
        base::TimeDelta::FromSeconds(kPrivetCancelationTimeoutSeconds));

    ongoing_ = false;
  }
}

void PrivetRegisterOperationImpl::CompleteRegistration() {
  next_response_handler_ =
      base::Bind(&PrivetRegisterOperationImpl::CompleteResponse,
                 base::Unretained(this));
  SendRequest(kPrivetActionComplete);
}

PrivetHTTPClient* PrivetRegisterOperationImpl::GetHTTPClient() {
  return privet_client_;
}

void PrivetRegisterOperationImpl::OnError(PrivetURLFetcher* fetcher,
                                          PrivetURLFetcher::ErrorType error) {
  ongoing_ = false;
  int visible_http_code = -1;
  FailureReason reason = FAILURE_NETWORK;

  if (error == PrivetURLFetcher::RESPONSE_CODE_ERROR) {
    visible_http_code = fetcher->response_code();
    reason = FAILURE_HTTP_ERROR;
  } else if (error == PrivetURLFetcher::JSON_PARSE_ERROR) {
    reason = FAILURE_MALFORMED_RESPONSE;
  } else if (error == PrivetURLFetcher::TOKEN_ERROR) {
    reason = FAILURE_TOKEN;
  } else if (error == PrivetURLFetcher::RETRY_ERROR) {
    reason = FAILURE_RETRY;
  }

  delegate_->OnPrivetRegisterError(this,
                                   current_action_,
                                   reason,
                                   visible_http_code,
                                   NULL);
}

void PrivetRegisterOperationImpl::OnParsedJson(
    PrivetURLFetcher* fetcher,
    const base::DictionaryValue* value,
    bool has_error) {
  if (has_error) {
    std::string error;
    value->GetString(kPrivetKeyError, &error);

    ongoing_ = false;
    delegate_->OnPrivetRegisterError(this,
                                     current_action_,
                                     FAILURE_JSON_ERROR,
                                     fetcher->response_code(),
                                     value);
    return;
  }

  // TODO(noamsml): Match the user&action with the user&action in the object,
  // and fail if different.

  next_response_handler_.Run(*value);
}

void PrivetRegisterOperationImpl::OnNeedPrivetToken(
    PrivetURLFetcher* fetcher,
    const PrivetURLFetcher::TokenCallback& callback) {
  privet_client_->RefreshPrivetToken(callback);
}

void PrivetRegisterOperationImpl::SendRequest(const std::string& action) {
  current_action_ = action;
  url_fetcher_ = privet_client_->CreateURLFetcher(
      CreatePrivetRegisterURL(action, user_), net::URLFetcher::POST, this);
  url_fetcher_->Start();
}

void PrivetRegisterOperationImpl::StartResponse(
    const base::DictionaryValue& value) {
  next_response_handler_ =
      base::Bind(&PrivetRegisterOperationImpl::GetClaimTokenResponse,
                 base::Unretained(this));

  SendRequest(kPrivetActionGetClaimToken);
}

void PrivetRegisterOperationImpl::GetClaimTokenResponse(
    const base::DictionaryValue& value) {
  std::string claimUrl;
  std::string claimToken;
  bool got_url = value.GetString(kPrivetKeyClaimURL, &claimUrl);
  bool got_token = value.GetString(kPrivetKeyClaimToken, &claimToken);
  if (got_url || got_token) {
    delegate_->OnPrivetRegisterClaimToken(this, claimToken, GURL(claimUrl));
  } else {
    delegate_->OnPrivetRegisterError(this,
                                     current_action_,
                                     FAILURE_MALFORMED_RESPONSE,
                                     -1,
                                     NULL);
  }
}

void PrivetRegisterOperationImpl::CompleteResponse(
    const base::DictionaryValue& value) {
  std::string id;
  value.GetString(kPrivetKeyDeviceID, &id);
  ongoing_ = false;
  expected_id_ = id;
  StartInfoOperation();
}

void PrivetRegisterOperationImpl::OnPrivetInfoDone(
    const base::DictionaryValue* value) {
  // TODO(noamsml): Simplify error case and depracate HTTP error value in
  // OnPrivetRegisterError.
  if (!value) {
    delegate_->OnPrivetRegisterError(this,
                                     kPrivetActionNameInfo,
                                     FAILURE_NETWORK,
                                     -1,
                                     NULL);
    return;
  }

  if (!value->HasKey(kPrivetInfoKeyID)) {
    if (value->HasKey(kPrivetKeyError)) {
      delegate_->OnPrivetRegisterError(this,
                                       kPrivetActionNameInfo,
                                        FAILURE_JSON_ERROR,
                                       -1,
                                       value);
    } else {
      delegate_->OnPrivetRegisterError(this,
                                       kPrivetActionNameInfo,
                                       FAILURE_MALFORMED_RESPONSE,
                                       -1,
                                       NULL);
    }
    return;
  }

  std::string id;

  if (!value->GetString(kPrivetInfoKeyID, &id) ||
      id != expected_id_) {
    delegate_->OnPrivetRegisterError(this,
                                     kPrivetActionNameInfo,
                                     FAILURE_MALFORMED_RESPONSE,
                                     -1,
                                     NULL);
  } else {
    delegate_->OnPrivetRegisterDone(this, id);
  }
}

void PrivetRegisterOperationImpl::StartInfoOperation() {
  info_operation_ = privet_client_->CreateInfoOperation(
      base::Bind(&PrivetRegisterOperationImpl::OnPrivetInfoDone,
                 base::Unretained(this)));
  info_operation_->Start();
}

PrivetRegisterOperationImpl::Cancelation::Cancelation(
    PrivetHTTPClient* privet_client,
    const std::string& user) {
  url_fetcher_ =
      privet_client->CreateURLFetcher(
          CreatePrivetRegisterURL(kPrivetActionCancel, user),
          net::URLFetcher::POST, this);
  url_fetcher_->DoNotRetryOnTransientError();
  url_fetcher_->Start();
}

PrivetRegisterOperationImpl::Cancelation::~Cancelation() {
}

void PrivetRegisterOperationImpl::Cancelation::OnError(
    PrivetURLFetcher* fetcher,
    PrivetURLFetcher::ErrorType error) {
}

void PrivetRegisterOperationImpl::Cancelation::OnParsedJson(
    PrivetURLFetcher* fetcher,
    const base::DictionaryValue* value,
    bool has_error) {
}

void PrivetRegisterOperationImpl::Cancelation::Cleanup() {
  // Nothing needs to be done, as base::Owned will delete this object,
  // this callback is just here to pass ownership of the Cancelation to
  // the message loop.
}

PrivetJSONOperationImpl::PrivetJSONOperationImpl(
    PrivetHTTPClient* privet_client,
    const std::string& path,
    const std::string& query_params,
    const PrivetJSONOperation::ResultCallback& callback)
    : privet_client_(privet_client),
      path_(path),
      query_params_(query_params),
      callback_(callback) {
}

PrivetJSONOperationImpl::~PrivetJSONOperationImpl() {
}

void PrivetJSONOperationImpl::Start() {
  url_fetcher_ = privet_client_->CreateURLFetcher(
      CreatePrivetParamURL(path_, query_params_), net::URLFetcher::GET, this);
  url_fetcher_->DoNotRetryOnTransientError();
  url_fetcher_->Start();
}

PrivetHTTPClient* PrivetJSONOperationImpl::GetHTTPClient() {
  return privet_client_;
}

void PrivetJSONOperationImpl::OnError(
    PrivetURLFetcher* fetcher,
    PrivetURLFetcher::ErrorType error) {
  callback_.Run(NULL);
}

void PrivetJSONOperationImpl::OnParsedJson(
    PrivetURLFetcher* fetcher,
    const base::DictionaryValue* value,
    bool has_error) {
  callback_.Run(value);
}

void PrivetJSONOperationImpl::OnNeedPrivetToken(
    PrivetURLFetcher* fetcher,
    const PrivetURLFetcher::TokenCallback& callback) {
  privet_client_->RefreshPrivetToken(callback);
}

PrivetDataReadOperationImpl::PrivetDataReadOperationImpl(
    PrivetHTTPClient* privet_client,
    const std::string& path,
    const std::string& query_params,
    const PrivetDataReadOperation::ResultCallback& callback)
    : privet_client_(privet_client),
      path_(path),
      query_params_(query_params),
      callback_(callback),
      has_range_(false),
      save_to_file_(false) {
}

PrivetDataReadOperationImpl::~PrivetDataReadOperationImpl() {
}


void PrivetDataReadOperationImpl::Start() {
  url_fetcher_ = privet_client_->CreateURLFetcher(
      CreatePrivetParamURL(path_, query_params_), net::URLFetcher::GET, this);
  url_fetcher_->DoNotRetryOnTransientError();

  if (has_range_) {
    url_fetcher_->SetByteRange(range_start_, range_end_);
  }

  if (save_to_file_) {
    url_fetcher_->SaveResponseToFile();
  }

  url_fetcher_->Start();
}

void PrivetDataReadOperationImpl::SetDataRange(int range_start, int range_end) {
  has_range_ = true;
  range_start_ = range_start;
  range_end_ = range_end;
}

void PrivetDataReadOperationImpl::SaveDataToFile() {
  save_to_file_ = false;
}

PrivetHTTPClient* PrivetDataReadOperationImpl::GetHTTPClient() {
  return privet_client_;
}

void PrivetDataReadOperationImpl::OnError(
    PrivetURLFetcher* fetcher,
    PrivetURLFetcher::ErrorType error) {
  callback_.Run(RESPONSE_TYPE_ERROR, std::string(), base::FilePath());
}

void PrivetDataReadOperationImpl::OnParsedJson(
    PrivetURLFetcher* fetcher,
    const base::DictionaryValue* value,
    bool has_error) {
  NOTREACHED();
}

void PrivetDataReadOperationImpl::OnNeedPrivetToken(
    PrivetURLFetcher* fetcher,
    const PrivetURLFetcher::TokenCallback& callback) {
  privet_client_->RefreshPrivetToken(callback);
}

bool PrivetDataReadOperationImpl::OnRawData(PrivetURLFetcher* fetcher,
                                            bool is_file,
                                            const std::string& data_str,
                                            const base::FilePath& file_path) {
  ResponseType type = (is_file) ? RESPONSE_TYPE_FILE : RESPONSE_TYPE_STRING;
  callback_.Run(type, data_str, file_path);
  return true;
}

PrivetLocalPrintOperationImpl::PrivetLocalPrintOperationImpl(
    PrivetHTTPClient* privet_client,
    PrivetLocalPrintOperation::Delegate* delegate)
    : privet_client_(privet_client),
      delegate_(delegate),
      use_pdf_(false),
      has_extended_workflow_(false),
      started_(false),
      offline_(false),
      dpi_(printing::kDefaultPdfDpi),
      invalid_job_retries_(0),
      weak_factory_(this) {
}

PrivetLocalPrintOperationImpl::~PrivetLocalPrintOperationImpl() {
}

void PrivetLocalPrintOperationImpl::Start() {
  DCHECK(!started_);

  // We need to get the /info response so we can know which APIs are available.
  // TODO(noamsml): Use cached info when available.
  info_operation_ = privet_client_->CreateInfoOperation(
      base::Bind(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone,
                 base::Unretained(this)));
  info_operation_->Start();

  started_ = true;
}

void PrivetLocalPrintOperationImpl::OnPrivetInfoDone(
    const base::DictionaryValue* value) {
  if (value && !value->HasKey(kPrivetKeyError)) {
    has_extended_workflow_ = false;
    bool has_printing = false;

    const base::ListValue* api_list;
    if (value->GetList(kPrivetInfoKeyAPIList, &api_list)) {
      for (size_t i = 0; i < api_list->GetSize(); i++) {
        std::string api;
        api_list->GetString(i, &api);
        if (api == kPrivetSubmitdocPath) {
          has_printing = true;
        } else if (api == kPrivetCreatejobPath) {
          has_extended_workflow_ = true;
        }
      }
    }

    if (!has_printing) {
      delegate_->OnPrivetPrintingError(this, -1);
      return;
    }

    StartInitialRequest();
  } else {
    delegate_->OnPrivetPrintingError(this, -1);
  }
}

void PrivetLocalPrintOperationImpl::StartInitialRequest() {
  use_pdf_ = false;
  ContentTypesCapability content_types;
  if (content_types.LoadFrom(capabilities_)) {
    use_pdf_ = content_types.Contains(kPrivetContentTypePDF) ||
               content_types.Contains(kPrivetContentTypeAny);
  }

  if (use_pdf_) {
    StartPrinting();
  } else {
    DpiCapability dpis;
    if (dpis.LoadFrom(capabilities_)) {
      dpi_ = std::max(dpis.GetDefault().horizontal, dpis.GetDefault().vertical);
    }
    StartConvertToPWG();
  }
}

void PrivetLocalPrintOperationImpl::DoCreatejob() {
  current_response_ = base::Bind(
      &PrivetLocalPrintOperationImpl::OnCreatejobResponse,
      base::Unretained(this));

  url_fetcher_= privet_client_->CreateURLFetcher(
      CreatePrivetURL(kPrivetCreatejobPath), net::URLFetcher::POST, this);
  url_fetcher_->SetUploadData(cloud_print::kContentTypeJSON,
                              ticket_.ToString());

  url_fetcher_->Start();
}

void PrivetLocalPrintOperationImpl::DoSubmitdoc() {
  current_response_ = base::Bind(
      &PrivetLocalPrintOperationImpl::OnSubmitdocResponse,
      base::Unretained(this));

  GURL url = CreatePrivetURL(kPrivetSubmitdocPath);

  url = net::AppendQueryParameter(url,
                                  kPrivetURLKeyClientName,
                                  kPrivetURLValueClientName);

  if (!user_.empty()) {
    url = net::AppendQueryParameter(url,
                                    kPrivetURLKeyUserName,
                                    user_);
  }

  base::string16 shortened_jobname;

  gfx::ElideString(base::UTF8ToUTF16(jobname_),
                   kPrivetLocalPrintMaxJobNameLength,
                   &shortened_jobname);

  if (!jobname_.empty()) {
    url = net::AppendQueryParameter(
        url, kPrivetURLKeyJobname, base::UTF16ToUTF8(shortened_jobname));
  }

  if (!jobid_.empty()) {
    url = net::AppendQueryParameter(url,
                                    kPrivetKeyJobID,
                                    jobid_);
  }

  if (offline_) {
    url = net::AppendQueryParameter(url,
                                    kPrivetURLKeyOffline,
                                    kPrivetURLValueOffline);
  }

  url_fetcher_= privet_client_->CreateURLFetcher(
      url, net::URLFetcher::POST, this);

  if (!use_pdf_) {
    url_fetcher_->SetUploadFilePath(kPrivetContentTypePWGRaster,
                                    pwg_file_path_);
  } else {
    // TODO(noamsml): Move to file-based upload data?
    std::string data_str((const char*)data_->front(), data_->size());
    url_fetcher_->SetUploadData(kPrivetContentTypePDF, data_str);
  }

  url_fetcher_->Start();
}

void PrivetLocalPrintOperationImpl::StartPrinting() {
  if (has_extended_workflow_ && jobid_.empty()) {
    DoCreatejob();
  } else {
    DoSubmitdoc();
  }
}

void PrivetLocalPrintOperationImpl::FillPwgRasterSettings(
    printing::PwgRasterSettings* transform_settings) {
  PwgRasterConfigCapability raster_capability;
  // If the raster capability fails to load, raster_capability will contain
  // the default value.
  raster_capability.LoadFrom(capabilities_);

  DuplexTicketItem duplex_item;
  DuplexType duplex_value = NO_DUPLEX;

  DocumentSheetBack document_sheet_back =
      raster_capability.value().document_sheet_back;

  if (duplex_item.LoadFrom(ticket_)) {
    duplex_value = duplex_item.value();
  }

  transform_settings->odd_page_transform = printing::TRANSFORM_NORMAL;
  switch (duplex_value) {
    case NO_DUPLEX:
      transform_settings->odd_page_transform = printing::TRANSFORM_NORMAL;
      break;
    case LONG_EDGE:
      if (document_sheet_back == ROTATED) {
        transform_settings->odd_page_transform = printing::TRANSFORM_ROTATE_180;
      } else if (document_sheet_back == FLIPPED) {
        transform_settings->odd_page_transform =
            printing::TRANSFORM_FLIP_VERTICAL;
      }
      break;
    case SHORT_EDGE:
      if (document_sheet_back == MANUAL_TUMBLE) {
        transform_settings->odd_page_transform = printing::TRANSFORM_ROTATE_180;
      } else if (document_sheet_back == FLIPPED) {
        transform_settings->odd_page_transform =
            printing::TRANSFORM_FLIP_HORIZONTAL;
      }
  }

  transform_settings->rotate_all_pages =
      raster_capability.value().rotate_all_pages;

  transform_settings->reverse_page_order =
      raster_capability.value().reverse_order_streaming;
}

void PrivetLocalPrintOperationImpl::StartConvertToPWG() {
  printing::PwgRasterSettings transform_settings;

  FillPwgRasterSettings(&transform_settings);

  if (!pwg_raster_converter_)
    pwg_raster_converter_ = PWGRasterConverter::CreateDefault();

  double scale = dpi_;
  scale /= printing::kPointsPerInch;
  // Make vertical rectangle to optimize streaming to printer. Fix orientation
  // by autorotate.
  gfx::Rect area(std::min(page_size_.width(), page_size_.height()) * scale,
                 std::max(page_size_.width(), page_size_.height()) * scale);
  pwg_raster_converter_->Start(
      data_,
      printing::PdfRenderSettings(area, dpi_, true),
      transform_settings,
      base::Bind(&PrivetLocalPrintOperationImpl::OnPWGRasterConverted,
                 base::Unretained(this)));
}

void PrivetLocalPrintOperationImpl::OnSubmitdocResponse(
    bool has_error,
    const base::DictionaryValue* value) {
  std::string error;
  // This error is only relevant in the case of extended workflow:
  // If the print job ID is invalid, retry createjob and submitdoc,
  // rather than simply retrying the current request.
  if (has_error && value->GetString(kPrivetKeyError, &error)) {
    if (has_extended_workflow_ &&
        error == kPrivetErrorInvalidPrintJob &&
        invalid_job_retries_ < kPrivetLocalPrintMaxRetries) {
      invalid_job_retries_++;

      int timeout = kPrivetLocalPrintDefaultTimeout;
      value->GetInteger(kPrivetKeyTimeout, &timeout);

      double random_scaling_factor =
          1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition;

      timeout = static_cast<int>(timeout * random_scaling_factor);

      timeout = std::max(timeout, kPrivetMinimumTimeout);

      base::MessageLoop::current()->PostDelayedTask(
          FROM_HERE, base::Bind(&PrivetLocalPrintOperationImpl::DoCreatejob,
                                weak_factory_.GetWeakPtr()),
          base::TimeDelta::FromSeconds(timeout));
    } else if (use_pdf_ && error == kPrivetErrorInvalidDocumentType) {
      use_pdf_ = false;
      StartConvertToPWG();
    } else {
      delegate_->OnPrivetPrintingError(this, 200);
    }

    return;
  }

  // If we've gotten this far, there are no errors, so we've effectively
  // succeeded.
  delegate_->OnPrivetPrintingDone(this);
}

void PrivetLocalPrintOperationImpl::OnCreatejobResponse(
    bool has_error,
    const base::DictionaryValue* value) {
  if (has_error) {
    delegate_->OnPrivetPrintingError(this, 200);
    return;
  }

  // Try to get job ID from value. If not, jobid_ will be empty and we will use
  // simple printing.
  value->GetString(kPrivetKeyJobID, &jobid_);

  DoSubmitdoc();
}

void PrivetLocalPrintOperationImpl::OnPWGRasterConverted(
    bool success,
    const base::FilePath& pwg_file_path) {
  if (!success) {
    delegate_->OnPrivetPrintingError(this, -1);
    return;
  }

  DCHECK(!pwg_file_path.empty());

  pwg_file_path_ = pwg_file_path;
  StartPrinting();
}

PrivetHTTPClient* PrivetLocalPrintOperationImpl::GetHTTPClient() {
  return privet_client_;
}

void PrivetLocalPrintOperationImpl::OnError(
    PrivetURLFetcher* fetcher,
    PrivetURLFetcher::ErrorType error) {
  delegate_->OnPrivetPrintingError(this, -1);
}

void PrivetLocalPrintOperationImpl::OnParsedJson(
    PrivetURLFetcher* fetcher,
    const base::DictionaryValue* value,
    bool has_error) {
  DCHECK(!current_response_.is_null());
  current_response_.Run(has_error, value);
}

void PrivetLocalPrintOperationImpl::OnNeedPrivetToken(
    PrivetURLFetcher* fetcher,
    const PrivetURLFetcher::TokenCallback& callback) {
  privet_client_->RefreshPrivetToken(callback);
}

void PrivetLocalPrintOperationImpl::SetData(base::RefCountedBytes* data) {
  DCHECK(!started_);
  data_ = data;
}

void PrivetLocalPrintOperationImpl::SetTicket(const std::string& ticket) {
  DCHECK(!started_);
  ticket_.InitFromString(ticket);
}

void PrivetLocalPrintOperationImpl::SetCapabilities(
    const std::string& capabilities) {
  DCHECK(!started_);
  capabilities_.InitFromString(capabilities);
}

void PrivetLocalPrintOperationImpl::SetUsername(const std::string& user) {
  DCHECK(!started_);
  user_= user;
}

void PrivetLocalPrintOperationImpl::SetJobname(const std::string& jobname) {
  DCHECK(!started_);
  jobname_ = jobname;
}

void PrivetLocalPrintOperationImpl::SetOffline(bool offline) {
  DCHECK(!started_);
  offline_ = offline;
}

void PrivetLocalPrintOperationImpl::SetPageSize(const gfx::Size& page_size) {
  DCHECK(!started_);
  page_size_ = page_size;
}

void PrivetLocalPrintOperationImpl::SetPWGRasterConverterForTesting(
    scoped_ptr<PWGRasterConverter> pwg_raster_converter) {
  pwg_raster_converter_ = pwg_raster_converter.Pass();
}

PrivetHTTPClientImpl::PrivetHTTPClientImpl(
    const std::string& name,
    const net::HostPortPair& host_port,
    net::URLRequestContextGetter* request_context)
    : name_(name), request_context_(request_context), host_port_(host_port) {}

PrivetHTTPClientImpl::~PrivetHTTPClientImpl() {
}

const std::string& PrivetHTTPClientImpl::GetName() {
  return name_;
}

scoped_ptr<PrivetJSONOperation> PrivetHTTPClientImpl::CreateInfoOperation(
    const PrivetJSONOperation::ResultCallback& callback) {
  return scoped_ptr<PrivetJSONOperation>(
      new PrivetInfoOperationImpl(this, callback));
}

scoped_ptr<PrivetURLFetcher> PrivetHTTPClientImpl::CreateURLFetcher(
    const GURL& url,
    net::URLFetcher::RequestType request_type,
    PrivetURLFetcher::Delegate* delegate) {
  GURL::Replacements replacements;
  replacements.SetHostStr(host_port_.host());
  std::string port(base::IntToString(host_port_.port()));  // Keep string alive.
  replacements.SetPortStr(port);
  return scoped_ptr<PrivetURLFetcher>(
      new PrivetURLFetcher(url.ReplaceComponents(replacements),
                           request_type,
                           request_context_.get(),
                           delegate));
}

void PrivetHTTPClientImpl::RefreshPrivetToken(
    const PrivetURLFetcher::TokenCallback& callback) {
  token_callbacks_.push_back(callback);

  if (!info_operation_) {
    info_operation_ = CreateInfoOperation(
        base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone,
                   base::Unretained(this)));
    info_operation_->Start();
  }
}

void PrivetHTTPClientImpl::OnPrivetInfoDone(
    const base::DictionaryValue* value) {
  info_operation_.reset();
  std::string token;

  // If this does not succeed, token will be empty, and an empty string
  // is our sentinel value, since empty X-Privet-Tokens are not allowed.
  if (value) {
    value->GetString(kPrivetInfoKeyToken, &token);
  }

  TokenCallbackVector token_callbacks;
  token_callbacks_.swap(token_callbacks);

  for (TokenCallbackVector::iterator i = token_callbacks.begin();
       i != token_callbacks.end(); i++) {
    i->Run(token);
  }
}

PrivetV1HTTPClientImpl::PrivetV1HTTPClientImpl(
    scoped_ptr<PrivetHTTPClient> info_client)
    : info_client_(info_client.Pass()) {
}

PrivetV1HTTPClientImpl::~PrivetV1HTTPClientImpl() {
}

const std::string& PrivetV1HTTPClientImpl::GetName() {
  return info_client()->GetName();
}

scoped_ptr<PrivetJSONOperation> PrivetV1HTTPClientImpl::CreateInfoOperation(
    const PrivetJSONOperation::ResultCallback& callback) {
  return info_client()->CreateInfoOperation(callback);
}

scoped_ptr<PrivetRegisterOperation>
PrivetV1HTTPClientImpl::CreateRegisterOperation(
    const std::string& user,
    PrivetRegisterOperation::Delegate* delegate) {
  return scoped_ptr<PrivetRegisterOperation>(
      new PrivetRegisterOperationImpl(info_client(), user, delegate));
}

scoped_ptr<PrivetJSONOperation>
PrivetV1HTTPClientImpl::CreateCapabilitiesOperation(
    const PrivetJSONOperation::ResultCallback& callback) {
  return scoped_ptr<PrivetJSONOperation>(new PrivetJSONOperationImpl(
      info_client(), kPrivetCapabilitiesPath, "", callback));
}

scoped_ptr<PrivetLocalPrintOperation>
PrivetV1HTTPClientImpl::CreateLocalPrintOperation(
    PrivetLocalPrintOperation::Delegate* delegate) {
  return scoped_ptr<PrivetLocalPrintOperation>(
      new PrivetLocalPrintOperationImpl(info_client(), delegate));
}

scoped_ptr<PrivetJSONOperation>
PrivetV1HTTPClientImpl::CreateStorageListOperation(
    const std::string& path,
    const PrivetJSONOperation::ResultCallback& callback) {
  std::string url_param =
      base::StringPrintf(kPrivetStorageParamPathFormat, path.c_str());
  return scoped_ptr<PrivetJSONOperation>(new PrivetJSONOperationImpl(
      info_client(), kPrivetStorageListPath, url_param, callback));
}

scoped_ptr<PrivetDataReadOperation>
PrivetV1HTTPClientImpl::CreateStorageReadOperation(
    const std::string& path,
    const PrivetDataReadOperation::ResultCallback& callback) {
  std::string url_param =
      base::StringPrintf(kPrivetStorageParamPathFormat, path.c_str());
  return scoped_ptr<PrivetDataReadOperation>(new PrivetDataReadOperationImpl(
      info_client(), kPrivetStorageContentPath, url_param, callback));
}

PrivetV3HTTPClientImpl::PrivetV3HTTPClientImpl(
    scoped_ptr<PrivetHTTPClient> info_client)
    : info_client_(info_client.Pass()) {
}

PrivetV3HTTPClientImpl::~PrivetV3HTTPClientImpl() {
}

const std::string& PrivetV3HTTPClientImpl::GetName() {
  return info_client()->GetName();
}

scoped_ptr<PrivetJSONOperation> PrivetV3HTTPClientImpl::CreateInfoOperation(
    const PrivetJSONOperation::ResultCallback& callback) {
  return info_client()->CreateInfoOperation(callback);
}

}  // namespace local_discovery
