//
// Copyright (C) 2011 The Android Open Source Project
//
// 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 UPDATE_ENGINE_PAYLOAD_CONSUMER_DOWNLOAD_ACTION_H_
#define UPDATE_ENGINE_PAYLOAD_CONSUMER_DOWNLOAD_ACTION_H_

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <memory>
#include <string>

#include "update_engine/common/action.h"
#include "update_engine/common/boot_control_interface.h"
#include "update_engine/common/http_fetcher.h"
#include "update_engine/payload_consumer/delta_performer.h"
#include "update_engine/payload_consumer/install_plan.h"
#include "update_engine/system_state.h"

// The Download Action downloads a specified url to disk. The url should point
// to an update in a delta payload format. The payload will be piped into a
// DeltaPerformer that will apply the delta to the disk.

namespace chromeos_update_engine {

class DownloadActionDelegate {
 public:
  virtual ~DownloadActionDelegate() = default;

  // Called periodically after bytes are received. This method will be invoked
  // only if the DownloadAction is running. |bytes_progressed| is the number of
  // bytes downloaded since the last call of this method, |bytes_received|
  // the number of bytes downloaded thus far and |total| is the number of bytes
  // expected.
  virtual void BytesReceived(uint64_t bytes_progressed,
                             uint64_t bytes_received,
                             uint64_t total) = 0;

  // Returns whether the download should be canceled, in which case the
  // |cancel_reason| error should be set to the reason why the download was
  // canceled.
  virtual bool ShouldCancel(ErrorCode* cancel_reason) = 0;

  // Called once the complete payload has been downloaded. Note that any errors
  // while applying or downloading the partial payload will result in this
  // method not being called.
  virtual void DownloadComplete() = 0;
};

class PrefsInterface;

class DownloadAction : public InstallPlanAction,
                       public HttpFetcherDelegate {
 public:
  // Debugging/logging
  static std::string StaticType() { return "DownloadAction"; }

  // Takes ownership of the passed in HttpFetcher. Useful for testing.
  // A good calling pattern is:
  // DownloadAction(prefs, boot_contol, hardware, system_state,
  //                new WhateverHttpFetcher);
  DownloadAction(PrefsInterface* prefs,
                 BootControlInterface* boot_control,
                 HardwareInterface* hardware,
                 SystemState* system_state,
                 HttpFetcher* http_fetcher);
  ~DownloadAction() override;

  // InstallPlanAction overrides.
  void PerformAction() override;
  void SuspendAction() override;
  void ResumeAction() override;
  void TerminateProcessing() override;
  std::string Type() const override { return StaticType(); }

  // Testing
  void SetTestFileWriter(FileWriter* writer) {
    writer_ = writer;
  }

  int GetHTTPResponseCode() { return http_fetcher_->http_response_code(); }

  // HttpFetcherDelegate methods (see http_fetcher.h)
  void ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes, size_t length) override;
  void SeekToOffset(off_t offset) override;
  void TransferComplete(HttpFetcher* fetcher, bool successful) override;
  void TransferTerminated(HttpFetcher* fetcher) override;

  DownloadActionDelegate* delegate() const { return delegate_; }
  void set_delegate(DownloadActionDelegate* delegate) {
    delegate_ = delegate;
  }

  HttpFetcher* http_fetcher() { return http_fetcher_.get(); }

  // Returns the p2p file id for the file being written or the empty
  // string if we're not writing to a p2p file.
  std::string p2p_file_id() { return p2p_file_id_; }

 private:
  // Closes the file descriptor for the p2p file being written and
  // clears |p2p_file_id_| to indicate that we're no longer sharing
  // the file. If |delete_p2p_file| is True, also deletes the file.
  // If there is no p2p file descriptor, this method does nothing.
  void CloseP2PSharingFd(bool delete_p2p_file);

  // Starts sharing the p2p file. Must be called before
  // WriteToP2PFile(). Returns True if this worked.
  bool SetupP2PSharingFd();

  // Writes |length| bytes of payload from |data| into |file_offset|
  // of the p2p file. Also does sanity checks; for example ensures we
  // don't end up with a file with holes in it.
  //
  // This method does nothing if SetupP2PSharingFd() hasn't been
  // called or if CloseP2PSharingFd() has been called.
  void WriteToP2PFile(const void* data, size_t length, off_t file_offset);

  // The InstallPlan passed in
  InstallPlan install_plan_;

  // SystemState required pointers.
  PrefsInterface* prefs_;
  BootControlInterface* boot_control_;
  HardwareInterface* hardware_;

  // Global context for the system.
  SystemState* system_state_;

  // Pointer to the HttpFetcher that does the http work.
  std::unique_ptr<HttpFetcher> http_fetcher_;

  // The FileWriter that downloaded data should be written to. It will
  // either point to *decompressing_file_writer_ or *delta_performer_.
  FileWriter* writer_;

  std::unique_ptr<DeltaPerformer> delta_performer_;

  // Used by TransferTerminated to figure if this action terminated itself or
  // was terminated by the action processor.
  ErrorCode code_;

  // For reporting status to outsiders
  DownloadActionDelegate* delegate_;
  uint64_t bytes_received_;
  bool download_active_{false};

  // The file-id for the file we're sharing or the empty string
  // if we're not using p2p to share.
  std::string p2p_file_id_;

  // The file descriptor for the p2p file used for caching the payload or -1
  // if we're not using p2p to share.
  int p2p_sharing_fd_;

  // Set to |false| if p2p file is not visible.
  bool p2p_visible_;

  DISALLOW_COPY_AND_ASSIGN(DownloadAction);
};

// We want to be sure that we're compiled with large file support on linux,
// just in case we find ourselves downloading large images.
static_assert(8 == sizeof(off_t), "off_t not 64 bit");

}  // namespace chromeos_update_engine

#endif  // UPDATE_ENGINE_PAYLOAD_CONSUMER_DOWNLOAD_ACTION_H_
