// Copyright (c) 2012 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 "components/web_resource/promo_resource_service.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/web_resource/notification_promo.h"
#include "components/web_resource/web_resource_pref_names.h"
#include "components/web_resource/web_resource_switches.h"
#include "url/gurl.h"

namespace web_resource {

namespace {

// Delay on first fetch so we don't interfere with startup.
const int kStartResourceFetchDelay = 5000;

// Delay between calls to fetch the promo json: 6 hours in production, and 3 min
// in debug.
const int kCacheUpdateDelay = 6 * 60 * 60 * 1000;
const int kTestCacheUpdateDelay = 3 * 60 * 1000;

// The promotion type used for Unpack() and ScheduleNotificationOnInit().
const NotificationPromo::PromoType kValidPromoTypes[] = {
#if defined(OS_ANDROID) || defined(OS_IOS)
    NotificationPromo::MOBILE_NTP_SYNC_PROMO,
#if defined(OS_IOS)
    NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO,
#endif  // defined(OS_IOS)
#else
    NotificationPromo::NTP_NOTIFICATION_PROMO,
    NotificationPromo::NTP_BUBBLE_PROMO,
#endif
};

GURL GetPromoResourceURL(version_info::Channel channel) {
  const std::string promo_server_url =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kPromoServerURL);
  return promo_server_url.empty() ? NotificationPromo::PromoServerURL(channel)
                                  : GURL(promo_server_url);
}

bool IsTest() {
  return base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kPromoServerURL);
}

int GetCacheUpdateDelay() {
  return IsTest() ? kTestCacheUpdateDelay : kCacheUpdateDelay;
}

}  // namespace

// static
void PromoResourceService::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0");
  NotificationPromo::RegisterPrefs(registry);
}

// static
void PromoResourceService::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  // TODO(dbeam): This is registered only for migration; remove in M28
  // when all prefs have been cleared.  http://crbug.com/168887
  registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0");
  NotificationPromo::RegisterProfilePrefs(registry);
}

// static
void PromoResourceService::MigrateUserPrefs(PrefService* user_prefs) {
  user_prefs->ClearPref(prefs::kNtpPromoResourceCacheUpdate);
  NotificationPromo::MigrateUserPrefs(user_prefs);
}

PromoResourceService::PromoResourceService(
    PrefService* local_state,
    version_info::Channel channel,
    const std::string& application_locale,
    net::URLRequestContextGetter* request_context,
    const char* disable_network_switch,
    const ParseJSONCallback& parse_json_callback)
    : WebResourceService(local_state,
                         GetPromoResourceURL(channel),
                         application_locale,  // append locale to URL
                         prefs::kNtpPromoResourceCacheUpdate,
                         kStartResourceFetchDelay,
                         GetCacheUpdateDelay(),
                         request_context,
                         disable_network_switch,
                         parse_json_callback),
      weak_ptr_factory_(this) {
  ScheduleNotificationOnInit();
}

PromoResourceService::~PromoResourceService() {}

scoped_ptr<PromoResourceService::StateChangedSubscription>
PromoResourceService::RegisterStateChangedCallback(
    const base::Closure& closure) {
  return callback_list_.Add(closure);
}

void PromoResourceService::ScheduleNotification(
    const NotificationPromo& notification_promo) {
  const double promo_start = notification_promo.StartTimeForGroup();
  const double promo_end = notification_promo.EndTime();

  if (promo_start > 0 && promo_end > 0) {
    const int64 ms_until_start = static_cast<int64>(
        (base::Time::FromDoubleT(promo_start) - base::Time::Now())
            .InMilliseconds());
    const int64 ms_until_end = static_cast<int64>(
        (base::Time::FromDoubleT(promo_end) - base::Time::Now())
            .InMilliseconds());
    if (ms_until_start > 0) {
      // Schedule the next notification to happen at the start of promotion.
      PostNotification(ms_until_start);
    } else if (ms_until_end > 0) {
      if (ms_until_start <= 0) {
        // The promo is active.  Notify immediately.
        PostNotification(0);
      }
      // Schedule the next notification to happen at the end of promotion.
      PostNotification(ms_until_end);
    } else {
      // The promo (if any) has finished.  Notify immediately.
      PostNotification(0);
    }
  } else {
    // The promo (if any) was apparently cancelled.  Notify immediately.
    PostNotification(0);
  }
}

void PromoResourceService::ScheduleNotificationOnInit() {
  // If the promo start is in the future, set a notification task to
  // invalidate the NTP cache at the time of the promo start.
  for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
    NotificationPromo notification_promo(prefs_);
    notification_promo.InitFromPrefs(kValidPromoTypes[i]);
    ScheduleNotification(notification_promo);
  }
}

void PromoResourceService::PostNotification(int64 delay_ms) {
  // Note that this could cause re-issuing a notification every time
  // we receive an update from a server if something goes wrong.
  // Given that this couldn't happen more frequently than every
  // kCacheUpdateDelay milliseconds, we should be fine.
  // TODO(achuith): This crashes if we post delay_ms = 0 to the message loop.
  // during startup.
  if (delay_ms > 0) {
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, base::Bind(&PromoResourceService::PromoResourceStateChange,
                              weak_ptr_factory_.GetWeakPtr()),
        base::TimeDelta::FromMilliseconds(delay_ms));
  } else if (delay_ms == 0) {
    PromoResourceStateChange();
  }
}

void PromoResourceService::PromoResourceStateChange() {
  callback_list_.Notify();
}

void PromoResourceService::Unpack(const base::DictionaryValue& parsed_json) {
  for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
    NotificationPromo notification_promo(prefs_);
    notification_promo.InitFromJson(parsed_json, kValidPromoTypes[i]);
    if (notification_promo.new_notification())
      ScheduleNotification(notification_promo);
  }
}

}  // namespace web_resource
