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

#ifndef UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_
#define UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_

#include <deque>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "update_engine/http_fetcher.h"

// This class is a simple wrapper around an HttpFetcher. The client
// specifies a vector of byte ranges. MultiRangeHttpFetcher will fetch bytes
// from those offsets, using the same bash fetcher for all ranges. Thus, the
// fetcher must support beginning a transfer after one has stopped. Pass -1
// as a length to specify unlimited length. It really only would make sense
// for the last range specified to have unlimited length, tho it is legal for
// other entries to have unlimited length.

// There are three states a MultiRangeHttpFetcher object will be in:
// - Stopped (start state)
// - Downloading
// - Pending transfer ended
// Various functions below that might change state indicate possible
// state changes.

namespace chromeos_update_engine {

class MultiRangeHttpFetcher : public HttpFetcher, public HttpFetcherDelegate {
 public:
  // Takes ownership of the passed in fetcher.
  explicit MultiRangeHttpFetcher(HttpFetcher* base_fetcher)
      : HttpFetcher(base_fetcher->proxy_resolver(),
                    base_fetcher->GetSystemState()),
        base_fetcher_(base_fetcher),
        base_fetcher_active_(false),
        pending_transfer_ended_(false),
        terminating_(false),
        current_index_(0),
        bytes_received_this_range_(0) {}
  ~MultiRangeHttpFetcher() override {}

  void ClearRanges() { ranges_.clear(); }

  void AddRange(off_t offset, size_t size) {
    CHECK_GT(size, static_cast<size_t>(0));
    ranges_.push_back(Range(offset, size));
  }

  void AddRange(off_t offset) {
    ranges_.push_back(Range(offset));
  }

  // HttpFetcher overrides.
  void SetOffset(off_t offset) override {}  // for now, doesn't support this

  void SetLength(size_t length) override {}  // unsupported
  void UnsetLength() override {}

  // Begins the transfer to the specified URL.
  // State change: Stopped -> Downloading
  // (corner case: Stopped -> Stopped for an empty request)
  void BeginTransfer(const std::string& url) override;

  // State change: Downloading -> Pending transfer ended
  void TerminateTransfer() override;

  void Pause() override { base_fetcher_->Pause(); }

  void Unpause() override { base_fetcher_->Unpause(); }

  // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
  void set_idle_seconds(int seconds) override {
    base_fetcher_->set_idle_seconds(seconds);
  }
  void set_retry_seconds(int seconds) override {
    base_fetcher_->set_retry_seconds(seconds);
  }
  // TODO(deymo): Determine if this method should be virtual in HttpFetcher so
  // this call is sent to the base_fetcher_.
  virtual void SetProxies(const std::deque<std::string>& proxies) {
    base_fetcher_->SetProxies(proxies);
  }

  inline size_t GetBytesDownloaded() override {
    return base_fetcher_->GetBytesDownloaded();
  }

  void set_low_speed_limit(int low_speed_bps, int low_speed_sec) override {
    base_fetcher_->set_low_speed_limit(low_speed_bps, low_speed_sec);
  }

  void set_connect_timeout(int connect_timeout_seconds) override {
    base_fetcher_->set_connect_timeout(connect_timeout_seconds);
  }

  void set_max_retry_count(int max_retry_count) override {
    base_fetcher_->set_max_retry_count(max_retry_count);
  }

 private:
  // A range object defining the offset and length of a download chunk.  Zero
  // length indicates an unspecified end offset (note that it is impossible to
  // request a zero-length range in HTTP).
  class Range {
   public:
    Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
    explicit Range(off_t offset) : offset_(offset), length_(0) {}

    inline off_t offset() const { return offset_; }
    inline size_t length() const { return length_; }

    inline bool HasLength() const { return (length_ > 0); }

    std::string ToString() const;

   private:
    off_t offset_;
    size_t length_;
  };

  typedef std::vector<Range> RangesVect;

  // State change: Stopped or Downloading -> Downloading
  void StartTransfer();

  // HttpFetcherDelegate overrides.
  // State change: Downloading -> Downloading or Pending transfer ended
  void ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override;

  // State change: Pending transfer ended -> Stopped
  void TransferEnded(HttpFetcher* fetcher, bool successful);
  // These two call TransferEnded():
  void TransferComplete(HttpFetcher* fetcher, bool successful) override;
  void TransferTerminated(HttpFetcher* fetcher) override;

  void Reset();

  std::unique_ptr<HttpFetcher> base_fetcher_;

  // If true, do not send any more data or TransferComplete to the delegate.
  bool base_fetcher_active_;

  // If true, the next fetcher needs to be started when TransferTerminated is
  // received from the current fetcher.
  bool pending_transfer_ended_;

  // True if we are waiting for base fetcher to terminate b/c we are
  // ourselves terminating.
  bool terminating_;

  RangesVect ranges_;

  RangesVect::size_type current_index_;  // index into ranges_
  size_t bytes_received_this_range_;

  DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
};

}  // namespace chromeos_update_engine

#endif  // UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_
