// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// 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 "cobalt/webdriver/session_driver.h"

#include <utility>

#include "base/logging.h"
#include "cobalt/base/log_message_handler.h"

namespace cobalt {
namespace webdriver {
namespace {

const char kBrowserLog[] = "browser";

// Default page-load timeout.
const int kPageLoadTimeoutInSeconds = 30;

// Max retries for the "can_retry" CommandResult case.
const int kMaxRetries = 5;

protocol::LogEntry::LogLevel SeverityToLogLevel(int severity) {
  switch (severity) {
    case logging::LOG_INFO:
      return protocol::LogEntry::kInfo;
    case logging::LOG_WARNING:
    case logging::LOG_ERROR:
      return protocol::LogEntry::kWarning;
    case logging::LOG_FATAL:
      return protocol::LogEntry::kSevere;
  }
  return protocol::LogEntry::kInfo;
}

}  // namespace

SessionDriver::SessionDriver(
    const protocol::SessionId& session_id,
    const CreateWindowDriverCallback& create_window_driver_callback,
    const WaitForNavigationFunction& wait_for_navigation)
    : session_id_(session_id),
      capabilities_(protocol::Capabilities::CreateActualCapabilities()),
      create_window_driver_callback_(create_window_driver_callback),
      wait_for_navigation_(wait_for_navigation),
      next_window_id_(0),
      logging_callback_id_(0) {
  logging_callback_id_ = base::LogMessageHandler::GetInstance()->AddCallback(
      base::Bind(&SessionDriver::LogMessageHandler, base::Unretained(this)));
  RefreshWindowDriver();
}

void SessionDriver::RefreshWindowDriver() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  window_driver_ = create_window_driver_callback_.Run(
      window_driver_ ? window_driver_->window_id() : GetUniqueWindowId());
}

SessionDriver::~SessionDriver() {
  // No more calls to LogMessageHandler will be made after this, so we can
  // safely be destructed.
  base::LogMessageHandler::GetInstance()->RemoveCallback(logging_callback_id_);
}

WindowDriver* SessionDriver::GetWindow(const protocol::WindowId& window_id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (protocol::WindowId::IsCurrent(window_id) ||
      window_driver_->window_id() == window_id) {
    return window_driver_.get();
  } else {
    return NULL;
  }
}

util::CommandResult<void> SessionDriver::Navigate(const GURL& url) {
  int retries = 0;
  util::CommandResult<void> result;
  do {
    result = window_driver_->Navigate(std::move(url));
  } while (result.can_retry() && (retries++ < kMaxRetries));
  if (result.is_success()) {
    // TODO: Use timeout as specified by the webdriver client.
    wait_for_navigation_.Run(
        base::TimeDelta::FromSeconds(kPageLoadTimeoutInSeconds));
  }
  return result;
}

util::CommandResult<protocol::Capabilities> SessionDriver::GetCapabilities() {
  return util::CommandResult<protocol::Capabilities>(capabilities_);
}

util::CommandResult<protocol::WindowId>
SessionDriver::GetCurrentWindowHandle() {
  return util::CommandResult<protocol::WindowId>(window_driver_->window_id());
}

util::CommandResult<std::vector<protocol::WindowId> >
SessionDriver::GetWindowHandles() {
  typedef util::CommandResult<std::vector<protocol::WindowId> > CommandResult;
  // There is only one window, so just return a list of that.
  std::vector<protocol::WindowId> window_handles;
  window_handles.push_back(window_driver_->window_id());
  return CommandResult(window_handles);
}

util::CommandResult<std::vector<std::string> > SessionDriver::GetLogTypes() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  typedef util::CommandResult<std::vector<std::string> > CommandResult;

  std::vector<std::string> log_types;
  // Only "browser" log is supported.
  log_types.push_back(kBrowserLog);
  return CommandResult(log_types);
}

util::CommandResult<std::vector<protocol::LogEntry> > SessionDriver::GetLog(
    const protocol::LogType& type) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  typedef util::CommandResult<std::vector<protocol::LogEntry> > CommandResult;
  // Return an empty log vector for unsupported log types.
  CommandResult result((LogEntryVector()));
  if (type.type() == kBrowserLog) {
    base::AutoLock auto_lock(log_lock_);
    result = CommandResult(log_entries_);
    log_entries_.clear();
  }
  return result;
}

util::CommandResult<std::string> SessionDriver::GetAlertText() {
  return util::CommandResult<std::string>(
      protocol::Response::kNoAlertOpenError);
}

util::CommandResult<void> SessionDriver::SwitchToWindow(
    const protocol::WindowId& window_id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (window_id == window_driver_->window_id()) {
    return util::CommandResult<void>(protocol::Response::kSuccess);
  } else {
    return util::CommandResult<void>(protocol::Response::kNoSuchWindow);
  }
}

protocol::WindowId SessionDriver::GetUniqueWindowId() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  std::string window_id = base::StringPrintf("window-%d", next_window_id_++);
  return protocol::WindowId(window_id);
}

bool SessionDriver::LogMessageHandler(int severity, const char* file, int line,
                                      size_t message_start,
                                      const std::string& str) {
  // Could be called from an arbitrary thread.
  base::Time log_time = base::Time::Now();
  protocol::LogEntry::LogLevel level = SeverityToLogLevel(severity);

  base::AutoLock auto_lock(log_lock_);
  log_entries_.push_back(protocol::LogEntry(log_time, level, str));
  // Don't capture this log entry - give other handlers a shot at it.
  return false;
}

}  // namespace webdriver
}  // namespace cobalt
