// 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 "net/proxy/polling_proxy_config_service.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
#include "base/threading/worker_pool.h"
#include "net/proxy/proxy_config.h"

namespace net {

// Reference-counted wrapper that does all the work (needs to be
// reference-counted since we post tasks between threads; may outlive
// the parent PollingProxyConfigService).
class PollingProxyConfigService::Core
    : public base::RefCountedThreadSafe<PollingProxyConfigService::Core> {
 public:
  Core(base::TimeDelta poll_interval,
       GetConfigFunction get_config_func)
      : get_config_func_(get_config_func),
        poll_interval_(poll_interval),
        have_initialized_origin_loop_(false),
        has_config_(false),
        poll_task_outstanding_(false),
        poll_task_queued_(false) {
  }

  // Called when the parent PollingProxyConfigService is destroyed
  // (observers should not be called past this point).
  void Orphan() {
    base::AutoLock l(lock_);
    origin_loop_proxy_ = NULL;
  }

  bool GetLatestProxyConfig(ProxyConfig* config) {
    LazyInitializeOriginLoop();
    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());

    OnLazyPoll();

    // If we have already retrieved the proxy settings (on worker thread)
    // then return what we last saw.
    if (has_config_) {
      *config = last_config_;
      return true;
    }
    return false;
  }

  void AddObserver(Observer* observer) {
    LazyInitializeOriginLoop();
    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
    observers_.AddObserver(observer);
  }

  void RemoveObserver(Observer* observer) {
    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
    observers_.RemoveObserver(observer);
  }

  // Check for a new configuration if enough time has elapsed.
  void OnLazyPoll() {
    LazyInitializeOriginLoop();
    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());

    if (last_poll_time_.is_null() ||
        (base::TimeTicks::Now() - last_poll_time_) > poll_interval_) {
      CheckForChangesNow();
    }
  }

  void CheckForChangesNow() {
    LazyInitializeOriginLoop();
    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());

    if (poll_task_outstanding_) {
      // Only allow one task to be outstanding at a time. If we get a poll
      // request while we are busy, we will defer it until the current poll
      // completes.
      poll_task_queued_ = true;
      return;
    }

    last_poll_time_ = base::TimeTicks::Now();
    poll_task_outstanding_ = true;
    poll_task_queued_ = false;
    base::WorkerPool::PostTask(
        FROM_HERE,
        base::Bind(&Core::PollOnWorkerThread, this, get_config_func_),
        true);
  }

 private:
  friend class base::RefCountedThreadSafe<Core>;
  ~Core() {}

  void PollOnWorkerThread(GetConfigFunction func) {
    ProxyConfig config;
    func(&config);

    base::AutoLock l(lock_);
    if (origin_loop_proxy_) {
      origin_loop_proxy_->PostTask(
          FROM_HERE,
          base::Bind(&Core::GetConfigCompleted, this, config));
    }
  }

  // Called after the worker thread has finished retrieving a configuration.
  void GetConfigCompleted(const ProxyConfig& config) {
    DCHECK(poll_task_outstanding_);
    poll_task_outstanding_ = false;

    if (!origin_loop_proxy_)
      return;  // Was orphaned (parent has already been destroyed).

    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());

    if (!has_config_ || !last_config_.Equals(config)) {
      // If the configuration has changed, notify the observers.
      has_config_ = true;
      last_config_ = config;
      FOR_EACH_OBSERVER(Observer, observers_,
                        OnProxyConfigChanged(config,
                                             ProxyConfigService::CONFIG_VALID));
    }

    if (poll_task_queued_)
      CheckForChangesNow();
  }

  void LazyInitializeOriginLoop() {
    // TODO(eroman): Really this should be done in the constructor, but right
    //               now chrome is constructing the ProxyConfigService on the
    //               UI thread so we can't cache the IO thread for the purpose
    //               of DCHECKs until the first call is made.
    if (!have_initialized_origin_loop_) {
      origin_loop_proxy_ = base::MessageLoopProxy::current();
      have_initialized_origin_loop_ = true;
    }
  }

  GetConfigFunction get_config_func_;
  ObserverList<Observer> observers_;
  ProxyConfig last_config_;
  base::TimeTicks last_poll_time_;
  base::TimeDelta poll_interval_;

  base::Lock lock_;
  scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_;

  bool have_initialized_origin_loop_;
  bool has_config_;
  bool poll_task_outstanding_;
  bool poll_task_queued_;
};

void PollingProxyConfigService::AddObserver(Observer* observer) {
  core_->AddObserver(observer);
}

void PollingProxyConfigService::RemoveObserver(Observer* observer) {
  core_->RemoveObserver(observer);
}

ProxyConfigService::ConfigAvailability
    PollingProxyConfigService::GetLatestProxyConfig(ProxyConfig* config) {
  return core_->GetLatestProxyConfig(config) ? CONFIG_VALID : CONFIG_PENDING;
}

void PollingProxyConfigService::OnLazyPoll() {
  core_->OnLazyPoll();
}

PollingProxyConfigService::PollingProxyConfigService(
    base::TimeDelta poll_interval,
    GetConfigFunction get_config_func)
    : core_(new Core(poll_interval, get_config_func)) {
}

PollingProxyConfigService::~PollingProxyConfigService() {
  core_->Orphan();
}

void PollingProxyConfigService::CheckForChangesNow() {
  core_->CheckForChangesNow();
}

}  // namespace net
