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

#ifndef CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_DATA_FETCHER_H_
#define CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_DATA_FETCHER_H_

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/timer/timer.h"
#include "chrome/browser/android/shortcut_info.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace content {
class WebContents;
}

namespace favicon_base {
struct FaviconRawBitmapResult;
}

namespace IPC {
class Message;
}

class GURL;
struct InstallableData;
struct WebApplicationInfo;

// Aysnchronously fetches and processes data needed to create a shortcut for an
// Android Home screen launcher.
//
// Because of the various asynchronous calls made by this class, it is
// refcounted to prevent the class from being prematurely deleted.  If the
// pointer to the ShortcutHelper becomes invalid, the pipeline should kill
// itself.
class AddToHomescreenDataFetcher
    : public base::RefCounted<AddToHomescreenDataFetcher>,
      public content::WebContentsObserver {
 public:
  class Observer {
   public:
    // Callded when the installable check is compelte.
    virtual void OnDidDetermineWebApkCompatibility(
        bool is_webapk_compatible) = 0;

    // Called when the title of the page is available.
    virtual void OnUserTitleAvailable(const base::string16& title) = 0;

    // Converts the icon into one that can be used on the Android Home screen.
    // |is_generated| is an out-param that indicates whether the icon was
    // generated by Chrome.
    virtual SkBitmap FinalizeLauncherIconInBackground(const SkBitmap& icon,
                                                      const GURL& url,
                                                      bool* is_generated) = 0;

    // Called when all the data needed to create a shortcut is available.
    virtual void OnDataAvailable(const ShortcutInfo& info,
                                 const SkBitmap& icon) = 0;

    protected:
     virtual ~Observer() {}
  };

  // Initialize the fetcher by requesting the information about the page from
  // the renderer process. The initialization is asynchronous and
  // OnDidGetWebApplicationInfo is expected to be called when finished.
  AddToHomescreenDataFetcher(content::WebContents* web_contents,
                             int ideal_icon_size_in_dp,
                             int minimum_icon_size_in_dp,
                             int ideal_splash_image_size_in_dp,
                             int minimum_splash_image_size_in_dp,
                             bool check_webapk_compatible,
                             Observer* observer);

  // Returns a callback which fetches the splash screen image to be stored for
  // the webapp with the specified |id|.
  base::Closure FetchSplashScreenImageCallback(const std::string& id);

  // IPC message received when the initialization is finished.
  void OnDidGetWebApplicationInfo(const WebApplicationInfo& web_app_info);

  // Accessors, etc.
  void set_weak_observer(Observer* observer) { weak_observer_ = observer; }
  bool is_ready() const { return is_ready_; }
  ShortcutInfo& shortcut_info() { return shortcut_info_; }
  const SkBitmap& shortcut_icon() const { return shortcut_icon_; }

 private:
  friend class base::RefCounted<AddToHomescreenDataFetcher>;

  ~AddToHomescreenDataFetcher() override;

  // WebContentsObserver:
  bool OnMessageReceived(const IPC::Message& message) override;

  // Called if either InstallableManager or the favicon fetch takes too long.
  void OnDataTimedout();

  // Called when InstallableManager finishes looking for a manifest and icon.
  void OnDidPerformInstallableCheck(const InstallableData& data);

  // Grabs the favicon for the current URL.
  void FetchFavicon();
  void OnFaviconFetched(
      const favicon_base::FaviconRawBitmapResult& bitmap_result);

  // Creates the launcher icon from the given bitmap. shortcut_info_.url is
  // used to generate an icon if there is no bitmap in |bitmap_result| or the
  // bitmap is not large enough.
  void CreateLauncherIconFromFaviconInBackground(
      const favicon_base::FaviconRawBitmapResult& bitmap_result);

  // Creates the launcher icon from the given |raw_icon|.
  void CreateLauncherIcon(const SkBitmap& raw_icon);
  void CreateLauncherIconInBackground(const SkBitmap& raw_icon);

  // Notifies the observer that the shortcut data is all available.
  void NotifyObserver(const SkBitmap& icon);

  Observer* weak_observer_;

  // The icon must only be set on the UI thread for thread safety.
  SkBitmap shortcut_icon_;
  ShortcutInfo shortcut_info_;
  GURL splash_screen_url_;

  base::CancelableTaskTracker favicon_task_tracker_;
  base::Timer data_timeout_timer_;

  const int ideal_icon_size_in_dp_;
  const int minimum_icon_size_in_dp_;
  const int ideal_splash_image_size_in_dp_;
  const int minimum_splash_image_size_in_dp_;

  // Indicates whether to check WebAPK compatibility.
  bool check_webapk_compatibility_;
  bool is_waiting_for_web_application_info_;
  bool is_installable_check_complete_;
  bool is_icon_saved_;
  bool is_ready_;

  DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcher);
};

#endif  // CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_DATA_FETCHER_H_
