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

#ifndef COBALT_SPEECH_URL_FETCHER_FAKE_H_
#define COBALT_SPEECH_URL_FETCHER_FAKE_H_

#include "cobalt/speech/speech_configuration.h"

#if defined(ENABLE_FAKE_MICROPHONE)

#include <memory>
#include <string>
#include <utility>

#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/timer/timer.h"
#include "net/base/host_port_pair.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"

namespace cobalt {
namespace speech {

class URLFetcherFake : public net::URLFetcher {
 public:
  URLFetcherFake(const GURL& url, net::URLFetcher::RequestType request_type,
                 net::URLFetcherDelegate* delegate);
  virtual ~URLFetcherFake();

  // net::URLFetcher implementation:
  void SetUploadData(const std::string& upload_content_type,
                     const std::string& upload_content) override {
    NOTREACHED();
  }
  void SetUploadFilePath(
      const std::string& upload_content_type, const base::FilePath& file_path,
      uint64_t range_offset, uint64_t range_length,
      scoped_refptr<base::TaskRunner> file_task_runner) override{};
  void SetUploadStreamFactory(
      const std::string& upload_content_type,
      const CreateUploadStreamCallback& callback) override{};
  void SetChunkedUpload(const std::string& upload_content_type) override;
  void AppendChunkToUpload(const std::string& data,
                           bool is_last_chunk) override;
  void SetLoadFlags(int load_flags) override { NOTREACHED(); }
  void SetAllowCredentials(bool allow_credentials) override {}
  int GetLoadFlags() const override {
    NOTREACHED();
    return 0;
  }
  void SetReferrer(const std::string& referrer) override { NOTREACHED(); }
  void SetReferrerPolicy(
      net::URLRequest::ReferrerPolicy referrer_policy) override {}
  void SetExtraRequestHeaders(
      const std::string& extra_request_headers) override {
    NOTREACHED();
  }
  void AddExtraRequestHeader(const std::string& header_line) override {
    NOTREACHED();
  }
  void SetRequestContext(
      net::URLRequestContextGetter* request_context_getter) override;
  void SetInitiator(const base::Optional<url::Origin>& initiator) override {}
  void SetURLRequestUserData(
      const void* key,
      const CreateDataCallback& create_data_callback) override {
    NOTREACHED();
  }
  void SetStopOnRedirect(bool stop_on_redirect) override { NOTREACHED(); }
  void SetAutomaticallyRetryOn5xx(bool retry) override { NOTREACHED(); }
  void SaveResponseToFileAtPath(
      const base::FilePath& file_path,
      scoped_refptr<base::SequencedTaskRunner> file_task_runner) override {}
  void SaveResponseToLargeString() override {}
  void SaveResponseToTemporaryFile(
      scoped_refptr<base::SequencedTaskRunner> file_task_runner) override {}
  void SaveResponseWithWriter(
      std::unique_ptr<net::URLFetcherResponseWriter> response_writer) override {
    response_data_writer_ = std::move(response_writer);
  }
  net::URLFetcherResponseWriter* GetResponseWriter() const override {
    return response_data_writer_.get();
  }
  void SetMaxRetriesOn5xx(int max_retries) override { NOTREACHED(); }
  int GetMaxRetriesOn5xx() const override {
    NOTREACHED();
    return 0;
  }
  base::TimeDelta GetBackoffDelay() const override {
    NOTREACHED();
    return base::TimeDelta();
  }
  void SetAutomaticallyRetryOnNetworkChanges(int max_retries) override {
    NOTREACHED();
  }
  const net::HttpRequestHeaders& GetRequestHeaders() const override {
    return extra_request_headers_;
  }
  net::HttpResponseHeaders* GetResponseHeaders() const override {
    NOTREACHED();
    return NULL;
  }
  net::HostPortPair GetSocketAddress() const override {
    NOTREACHED();
    return net::HostPortPair();
  }
  const net::ProxyServer& ProxyServerUsed() const override {
    NOTREACHED();
    return proxy_server_;
  }
  bool WasFetchedViaProxy() const override {
    NOTREACHED();
    return false;
  }
  bool WasCached() const override {
    NOTREACHED();
    return false;
  }
  int64_t GetReceivedResponseContentLength() const override {
    NOTREACHED();
    return 1;
  }
  int64_t GetTotalReceivedBytes() const override {
    NOTREACHED();
    return 1;
  }
  void Start() override;
  const GURL& GetOriginalURL() const override { return original_url_; }
  const GURL& GetURL() const override { return original_url_; }
  const net::URLRequestStatus& GetStatus() const override;
  int GetResponseCode() const override;
  void ReceivedContentWasMalformed() override { NOTREACHED(); }
  bool GetResponseAsString(std::string* out_response_string) const override {
    NOTREACHED();
    return false;
  }
  bool GetResponseAsFilePath(bool take_ownership,
                             base::FilePath* out_response_path) const override {
    NOTREACHED();
    return false;
  }
  bool GetResponseAsLargeString(
      std::string* out_response_string) const override {
    NOTREACHED();
    return false;
  }

 private:
  void OnURLFetchDownloadData();

  GURL original_url_;
  net::URLFetcherDelegate* delegate_;
  bool is_chunked_upload_;
  int download_index_;
  net::URLRequestStatus fake_status_;
  base::Optional<base::RepeatingTimer> download_timer_;
  net::ProxyServer proxy_server_;
  std::unique_ptr<net::URLFetcherResponseWriter> response_data_writer_;
  net::HttpRequestHeaders extra_request_headers_;
  THREAD_CHECKER(thread_checker_);
};

}  // namespace speech
}  // namespace cobalt

#endif  // defined(ENABLE_FAKE_MICROPHONE)
#endif  // COBALT_SPEECH_URL_FETCHER_FAKE_H_
