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

#include "remoting/test/chromoting_test_driver_environment.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "remoting/test/access_token_fetcher.h"
#include "remoting/test/host_list_fetcher.h"
#include "remoting/test/refresh_token_store.h"

namespace remoting {
namespace test {

ChromotingTestDriverEnvironment* g_chromoting_shared_data = nullptr;

ChromotingTestDriverEnvironment::EnvironmentOptions::EnvironmentOptions() {
}

ChromotingTestDriverEnvironment::EnvironmentOptions::~EnvironmentOptions() {
}

ChromotingTestDriverEnvironment::ChromotingTestDriverEnvironment(
    const EnvironmentOptions& options)
    : host_name_(options.host_name),
      host_jid_(options.host_jid),
      user_name_(options.user_name),
      pin_(options.pin),
      refresh_token_file_path_(options.refresh_token_file_path),
      test_access_token_fetcher_(nullptr),
      test_refresh_token_store_(nullptr),
      test_host_list_fetcher_(nullptr) {
  DCHECK(!user_name_.empty());
  DCHECK(!host_name_.empty());
}

ChromotingTestDriverEnvironment::~ChromotingTestDriverEnvironment() {
}

bool ChromotingTestDriverEnvironment::Initialize(
    const std::string& auth_code) {
  if (!access_token_.empty()) {
    return true;
  }

  if (!base::MessageLoop::current()) {
    message_loop_.reset(new base::MessageLoopForIO);
  }

  // If a unit test has set |test_refresh_token_store_| then we should use it
  // below.  Note that we do not want to destroy the test object.
  std::unique_ptr<RefreshTokenStore> temporary_refresh_token_store;
  RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
  if (!refresh_token_store) {
    temporary_refresh_token_store =
        RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
    refresh_token_store = temporary_refresh_token_store.get();
  }

  // Check to see if we have a refresh token stored for this user.
  refresh_token_ = refresh_token_store->FetchRefreshToken();
  if (refresh_token_.empty()) {
    // This isn't necessarily an error as this might be a first run scenario.
    VLOG(2) << "No refresh token stored for " << user_name_;

    if (auth_code.empty()) {
      // No token and no Auth code means no service connectivity, bail!
      LOG(ERROR) << "Cannot retrieve an access token without a stored refresh"
                 << " token on disk or an auth_code passed into the tool";
      return false;
    }
  }

  if (!RetrieveAccessToken(auth_code)) {
    // If we cannot retrieve an access token, then nothing is going to work.
    // Let the caller know that our object is not ready to be used.
    return false;
  }

  return true;
}

void ChromotingTestDriverEnvironment::DisplayHostList() {
  const char kHostAvailabilityFormatString[] = "%-45s%-15s%-35s";

  LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
                                  "Host Name", "Host Status", "Host JID");
  LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
                                  "---------", "-----------", "--------");

  std::string status;
  for (const HostInfo& host_info : host_list_) {
    HostStatus host_status = host_info.status;
    if (host_status == kHostStatusOnline) {
      status = "ONLINE";
    } else if (host_status == kHostStatusOffline) {
      status = "OFFLINE";
    } else {
      status = "UNKNOWN";
    }

    LOG(INFO) << base::StringPrintf(
        kHostAvailabilityFormatString, host_info.host_name.c_str(),
        status.c_str(), host_info.host_jid.c_str());
  }
}

bool ChromotingTestDriverEnvironment::WaitForHostOnline(
    const std::string& host_jid,
    const std::string& host_name) {
  if (host_list_.empty()) {
    RetrieveHostList();
  }

  // Refresh the |host_list_| periodically to check if expected JID is online.
  const base::TimeDelta kTotalTimeInSeconds = base::TimeDelta::FromSeconds(60);
  const base::TimeDelta kSleepTimeInSeconds = base::TimeDelta::FromSeconds(5);
  const int kMaxIterations = kTotalTimeInSeconds / kSleepTimeInSeconds;

  int num_iterations = 0;
  while (num_iterations < kMaxIterations) {
    if (host_info_.IsReadyForConnection()) {
      if (num_iterations > 0) {
        VLOG(0) << "Host online after: "
                << num_iterations * kSleepTimeInSeconds.InSeconds()
                << " seconds.";
      }
      return true;
    }

    // Wait a while before refreshing host list.
    base::PlatformThread::Sleep(kSleepTimeInSeconds);
    RefreshHostList();
    ++num_iterations;
  }

  LOG(ERROR) << "Host with JID '" << host_jid << "' still not online after "
             << num_iterations * kSleepTimeInSeconds.InSeconds() << " seconds.";
  return false;
}

void ChromotingTestDriverEnvironment::SetAccessTokenFetcherForTest(
    AccessTokenFetcher* access_token_fetcher) {
  DCHECK(access_token_fetcher);

  test_access_token_fetcher_ = access_token_fetcher;
}

void ChromotingTestDriverEnvironment::SetRefreshTokenStoreForTest(
    RefreshTokenStore* refresh_token_store) {
  DCHECK(refresh_token_store);

  test_refresh_token_store_ = refresh_token_store;
}

void ChromotingTestDriverEnvironment::SetHostListFetcherForTest(
    HostListFetcher* host_list_fetcher) {
  DCHECK(host_list_fetcher);

  test_host_list_fetcher_ = host_list_fetcher;
}

void ChromotingTestDriverEnvironment::SetHostNameForTest(
    const std::string& host_name) {
  host_name_ = host_name;
}

void ChromotingTestDriverEnvironment::SetHostJidForTest(
    const std::string& host_jid) {
  host_jid_ = host_jid;
}

void ChromotingTestDriverEnvironment::TearDown() {
  // Letting the MessageLoop tear down during the test destructor results in
  // errors after test completion, when the MessageLoop dtor touches the
  // registered AtExitManager. The AtExitManager is torn down before the test
  // destructor is executed, so we tear down the MessageLoop here, while it is
  // still valid.
  message_loop_.reset();
}

bool ChromotingTestDriverEnvironment::RetrieveAccessToken(
    const std::string& auth_code) {
  base::RunLoop run_loop;

  access_token_.clear();

  AccessTokenCallback access_token_callback =
      base::Bind(&ChromotingTestDriverEnvironment::OnAccessTokenRetrieved,
                 base::Unretained(this), run_loop.QuitClosure());

  // If a unit test has set |test_access_token_fetcher_| then we should use it
  // below.  Note that we do not want to destroy the test object at the end of
  // the function which is why we have the dance below.
  std::unique_ptr<AccessTokenFetcher> temporary_access_token_fetcher;
  AccessTokenFetcher* access_token_fetcher = test_access_token_fetcher_;
  if (!access_token_fetcher) {
    temporary_access_token_fetcher.reset(new AccessTokenFetcher());
    access_token_fetcher = temporary_access_token_fetcher.get();
  }

  if (!auth_code.empty()) {
    // If the user passed in an authcode, then use it to retrieve an
    // updated access/refresh token.
    access_token_fetcher->GetAccessTokenFromAuthCode(auth_code,
                                                     access_token_callback);
  } else {
    DCHECK(!refresh_token_.empty());

    access_token_fetcher->GetAccessTokenFromRefreshToken(refresh_token_,
                                                         access_token_callback);
  }

  run_loop.Run();

  // If we were using an auth_code and received a valid refresh token,
  // then we want to store it locally.  If we had an auth code and did not
  // receive a refresh token, then we should let the user know and exit.
  if (!auth_code.empty()) {
    if (!refresh_token_.empty()) {
      // If a unit test has set |test_refresh_token_store_| then we should use
      // it below.  Note that we do not want to destroy the test object.
      std::unique_ptr<RefreshTokenStore> temporary_refresh_token_store;
      RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
      if (!refresh_token_store) {
        temporary_refresh_token_store =
            RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
        refresh_token_store = temporary_refresh_token_store.get();
      }

      if (!refresh_token_store->StoreRefreshToken(refresh_token_)) {
        // If we failed to persist the refresh token, then we should let the
        // user sort out the issue before continuing.
        return false;
      }
    } else {
      LOG(ERROR) << "Failed to use AUTH CODE to retrieve a refresh token.\n"
                 << "Was the one-time use AUTH CODE used more than once?";
      return false;
    }
  }

  if (access_token_.empty()) {
    LOG(ERROR) << "Failed to retrieve access token.";
    return false;
  }

  return true;
}

void ChromotingTestDriverEnvironment::OnAccessTokenRetrieved(
    base::Closure done_closure,
    const std::string& retrieved_access_token,
    const std::string& retrieved_refresh_token) {
  VLOG(1) << "OnAccessTokenRetrieved() Called";
  VLOG(1) << "Access Token: " << retrieved_access_token;

  access_token_ = retrieved_access_token;
  refresh_token_ = retrieved_refresh_token;

  done_closure.Run();
}

bool ChromotingTestDriverEnvironment::RefreshHostList() {
  host_list_.clear();

  return RetrieveHostList();
}

bool ChromotingTestDriverEnvironment::RetrieveHostList() {
  base::RunLoop run_loop;

  // Clear the previous host info.
  host_info_ = HostInfo();

  // If a unit test has set |test_host_list_fetcher_| then we should use it
  // below.  Note that we do not want to destroy the test object at the end of
  // the function which is why we have the dance below.
  std::unique_ptr<HostListFetcher> temporary_host_list_fetcher;
  HostListFetcher* host_list_fetcher = test_host_list_fetcher_;
  if (!host_list_fetcher) {
    temporary_host_list_fetcher.reset(new HostListFetcher());
    host_list_fetcher = temporary_host_list_fetcher.get();
  }

  remoting::test::HostListFetcher::HostlistCallback host_list_callback =
      base::Bind(&ChromotingTestDriverEnvironment::OnHostListRetrieved,
                 base::Unretained(this), run_loop.QuitClosure());

  host_list_fetcher->RetrieveHostlist(access_token_, host_list_callback);

  run_loop.Run();

  if (host_list_.empty()) {
    // Note: Access token may have expired, but it is unlikely.
    LOG(ERROR) << "Retrieved host list is empty.\n"
               << "Does the account have hosts set up?";
    return false;
  }

  DisplayHostList();
  for (HostInfo& host_info : host_list_) {
    // The JID is optional so we consider an empty string to be a '*' match.
    bool host_jid_match =
        host_jid_.empty() || (host_jid_ == host_info.host_jid);
    bool host_name_match = host_name_ == host_info.host_name;

    if (host_name_match && host_jid_match) {
      host_info_ = host_info;

      if (host_info.IsReadyForConnection()) {
        return true;
      } else {
        LOG(WARNING) << "Host '" << host_name_ << "' with JID '" << host_jid_
                     << "' not online.";
        return false;
      }
    }
  }
  LOG(WARNING) << "Host '" << host_name_ << "' with JID '" << host_jid_
               << "' not found in host list.";
  return false;
}

void ChromotingTestDriverEnvironment::OnHostListRetrieved(
    base::Closure done_closure,
    const std::vector<HostInfo>& retrieved_host_list) {
  VLOG(1) << "OnHostListRetrieved() Called";

  host_list_ = retrieved_host_list;

  done_closure.Run();
}

}  // namespace test
}  // namespace remoting
