//
// Copyright (C) 2012 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.
//

#include "shill/portal_detector.h"

#include <string>

#include <base/bind.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/connection.h"
#include "shill/connectivity_trial.h"
#include "shill/logging.h"

using base::Bind;
using base::Callback;
using base::StringPrintf;
using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kPortal;
static string ObjectID(Connection* c) { return c->interface_name(); }
}

const int PortalDetector::kDefaultCheckIntervalSeconds = 30;
const char PortalDetector::kDefaultCheckPortalList[] = "ethernet,wifi,cellular";

const int PortalDetector::kMaxRequestAttempts = 3;
const int PortalDetector::kMinTimeBetweenAttemptsSeconds = 3;
const int PortalDetector::kRequestTimeoutSeconds = 10;
const int PortalDetector::kMaxFailuresInContentPhase = 2;

PortalDetector::PortalDetector(
    ConnectionRefPtr connection,
    EventDispatcher* dispatcher,
    const Callback<void(const PortalDetector::Result&)>& callback)
    : attempt_count_(0),
      attempt_start_time_((struct timeval){0}),
      connection_(connection),
      dispatcher_(dispatcher),
      weak_ptr_factory_(this),
      portal_result_callback_(callback),
      time_(Time::GetInstance()),
      failures_in_content_phase_(0),
      connectivity_trial_(
          new ConnectivityTrial(connection_,
                                dispatcher_,
                                kRequestTimeoutSeconds,
                                Bind(&PortalDetector::CompleteAttempt,
                                     weak_ptr_factory_.GetWeakPtr()))) {}

PortalDetector::~PortalDetector() {
  Stop();
}

bool PortalDetector::Start(const string& url_string) {
  return StartAfterDelay(url_string, 0);
}

bool PortalDetector::StartAfterDelay(const string& url_string,
                                     int delay_seconds) {
  SLOG(connection_.get(), 3) << "In " << __func__;

  if (!connectivity_trial_->Start(url_string, delay_seconds * 1000)) {
    return false;
  }
  attempt_count_ = 1;
  // The attempt_start_time_ is calculated based on the current time and
  // |delay_seconds|.  This is used to determine if a portal detection attempt
  // is in progress.
  UpdateAttemptTime(delay_seconds);
  // If we're starting a new set of attempts, discard past failure history.
  failures_in_content_phase_ = 0;
  return true;
}

void PortalDetector::Stop() {
  SLOG(connection_.get(), 3) << "In " << __func__;

  attempt_count_ = 0;
  failures_in_content_phase_ = 0;
  if (connectivity_trial_.get())
    connectivity_trial_->Stop();
}

// IsInProgress returns true if a ConnectivityTrial is actively testing the
// connection.  If Start has been called, but the trial was delayed,
// IsInProgress will return false.  PortalDetector implements this by
// calculating the start time of the next ConnectivityTrial.  After an initial
// trial and in the case where multiple attempts may be tried, IsInProgress will
// return true.
bool PortalDetector::IsInProgress() {
  if (attempt_count_ > 1)
    return true;
  if (attempt_count_ == 1 && connectivity_trial_.get())
    return connectivity_trial_->IsActive();
  return false;
}

void PortalDetector::CompleteAttempt(ConnectivityTrial::Result trial_result) {
  Result result = Result(trial_result);
  if (trial_result.status == ConnectivityTrial::kStatusFailure &&
      trial_result.phase == ConnectivityTrial::kPhaseContent) {
    failures_in_content_phase_++;
  }

  LOG(INFO) << StringPrintf("Portal detection completed attempt %d with "
                            "phase==%s, status==%s, failures in content==%d",
                            attempt_count_,
                            ConnectivityTrial::PhaseToString(
                                trial_result.phase).c_str(),
                            ConnectivityTrial::StatusToString(
                                trial_result.status).c_str(),
                            failures_in_content_phase_);

  if (trial_result.status == ConnectivityTrial::kStatusSuccess ||
      attempt_count_ >= kMaxRequestAttempts ||
      failures_in_content_phase_ >= kMaxFailuresInContentPhase) {
    result.num_attempts = attempt_count_;
    result.final = true;
    Stop();
  } else {
    attempt_count_++;
    int retry_delay_seconds = AdjustStartDelay(0);
    connectivity_trial_->Retry(retry_delay_seconds * 1000);
    UpdateAttemptTime(retry_delay_seconds);
  }
  portal_result_callback_.Run(result);
}

void PortalDetector::UpdateAttemptTime(int delay_seconds) {
  time_->GetTimeMonotonic(&attempt_start_time_);
  struct timeval delay_timeval = { delay_seconds, 0 };
  timeradd(&attempt_start_time_, &delay_timeval, &attempt_start_time_);
}


int PortalDetector::AdjustStartDelay(int init_delay_seconds) {
  int next_attempt_delay_seconds = 0;
  if (attempt_count_ > 0) {
    // Ensure that attempts are spaced at least by a minimal interval.
    struct timeval now, elapsed_time;
    time_->GetTimeMonotonic(&now);
    timersub(&now, &attempt_start_time_, &elapsed_time);
    SLOG(connection_.get(), 4) << "Elapsed time from previous attempt is "
                               << elapsed_time.tv_sec << " seconds.";
    if (elapsed_time.tv_sec < kMinTimeBetweenAttemptsSeconds) {
      next_attempt_delay_seconds = kMinTimeBetweenAttemptsSeconds -
                                   elapsed_time.tv_sec;
    }
  } else {
    LOG(FATAL) << "AdjustStartDelay in PortalDetector called without "
                  "previous attempts";
  }
  SLOG(connection_.get(), 3) << "Adjusting trial start delay from "
                             << init_delay_seconds << " seconds to "
                             << next_attempt_delay_seconds << " seconds.";
  return next_attempt_delay_seconds;
}

}  // namespace shill
