/*
 * Copyright (C) 2021 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 "host/libs/confui/session.h"

#include <algorithm>

#include "common/libs/utils/contains.h"
#include "host/libs/confui/secure_input.h"

namespace cuttlefish {
namespace confui {

Session::Session(const std::string& session_name,
                 const std::uint32_t display_num, ConfUiRenderer& host_renderer,
                 HostModeCtrl& host_mode_ctrl, const std::string& locale)
    : session_id_{session_name},
      display_num_{display_num},
      renderer_{host_renderer},
      host_mode_ctrl_{host_mode_ctrl},
      locale_{locale},
      state_{MainLoopState::kInit},
      saved_state_{MainLoopState::kInit} {}

/** return grace period + alpha
 *
 * grace period is the gap between user seeing the dialog
 * and the UI starts to take the user inputs
 * Grace period should be at least 1s.
 * Session requests the Renderer to render the dialog,
 * but it might not be immediate. So, add alpha to 1s
 */
static const std::chrono::milliseconds GetGracePeriod() {
  using std::literals::chrono_literals::operator""ms;
  return 1000ms + 100ms;
}

bool Session::IsReadyForUserInput() const {
  using std::literals::chrono_literals::operator""ms;
  if (!start_time_) {
    return false;
  }
  const auto right_now = Clock::now();
  return (right_now - *start_time_) >= GetGracePeriod();
}

bool Session::RenderDialog() {
  auto result =
      renderer_.RenderDialog(display_num_, prompt_text_, locale_, ui_options_);
  if (!result.ok()) {
    LOG(ERROR) << result.error().Trace();
    return false;
  }
  return true;
}

MainLoopState Session::Transition(SharedFD& hal_cli, const FsmInput fsm_input,
                                  const ConfUiMessage& conf_ui_message) {
  bool should_keep_running = false;
  bool already_terminated = false;
  switch (state_) {
    case MainLoopState::kInit: {
      should_keep_running = HandleInit(hal_cli, fsm_input, conf_ui_message);
    } break;
    case MainLoopState::kInSession: {
      should_keep_running =
          HandleInSession(hal_cli, fsm_input, conf_ui_message);
    } break;
    case MainLoopState::kWaitStop: {
      if (IsUserInput(fsm_input)) {
        ConfUiLog(VERBOSE) << "User input ignored " << ToString(fsm_input)
                           << " : " << ToString(conf_ui_message)
                           << " at the state " << ToString(state_);
      }
      should_keep_running = HandleWaitStop(hal_cli, fsm_input);
    } break;
    case MainLoopState::kTerminated: {
      already_terminated = true;
    } break;
    default:
      ConfUiLog(FATAL) << "Must not be in the state of " << ToString(state_);
      break;
  }
  if (!should_keep_running && !already_terminated) {
    ScheduleToTerminate();
  }
  return state_;
};

void Session::CleanUp() {
  if (state_ != MainLoopState::kAwaitCleanup) {
    ConfUiLog(FATAL) << "Clean up a session only when in kAwaitCleanup";
  }
  state_ = MainLoopState::kTerminated;
  // common action done when the state is back to init state
  host_mode_ctrl_.SetMode(HostModeCtrl::ModeType::kAndroidMode);
}

void Session::ScheduleToTerminate() {
  state_ = MainLoopState::kAwaitCleanup;
  saved_state_ = MainLoopState::kInvalid;
}

bool Session::ReportErrorToHal(SharedFD hal_cli, const std::string& msg) {
  ScheduleToTerminate();
  if (!SendAck(hal_cli, session_id_, false, msg)) {
    ConfUiLog(ERROR) << "I/O error in sending ack to report rendering failure";
    return false;
  }
  return true;
}

void Session::Abort() {
  ConfUiLog(VERBOSE) << "Abort is called";
  ScheduleToTerminate();
  return;
}

void Session::UserAbort(SharedFD hal_cli) {
  ConfUiLog(VERBOSE) << "it is a user abort input.";
  SendAbortCmd(hal_cli, GetId());
  Abort();
  ScheduleToTerminate();
}

bool Session::HandleInit(SharedFD hal_cli, const FsmInput fsm_input,
                         const ConfUiMessage& conf_ui_message) {
  if (IsUserInput(fsm_input)) {
    // ignore user input
    state_ = MainLoopState::kInit;
    return true;
  }

  ConfUiLog(VERBOSE) << ToString(fsm_input) << "is handled in HandleInit";
  if (fsm_input != FsmInput::kHalStart) {
    ConfUiLog(ERROR) << "invalid cmd for Init State:" << ToString(fsm_input);
    // ReportErrorToHal returns true if error report was successful
    // However, anyway we abort this session on the host
    ReportErrorToHal(hal_cli, HostError::kSystemError);
    return false;
  }

  // Start Session
  ConfUiLog(VERBOSE) << "Sending ack to hal_cli: "
                     << Enum2Base(ConfUiCmd::kCliAck);
  host_mode_ctrl_.SetMode(HostModeCtrl::ModeType::kConfUI_Mode);

  auto start_cmd_msg = static_cast<const ConfUiStartMessage&>(conf_ui_message);
  prompt_text_ = start_cmd_msg.GetPromptText();
  locale_ = start_cmd_msg.GetLocale();
  extra_data_ = start_cmd_msg.GetExtraData();
  ui_options_ = start_cmd_msg.GetUiOpts();

  // cbor_ can be correctly created after the session received kStart cmd
  // at runtime
  cbor_ = std::make_unique<Cbor>(prompt_text_, extra_data_);
  if (cbor_->IsMessageTooLong()) {
    ConfUiLog(ERROR) << "The prompt text and extra_data are too long to be "
                     << "properly encoded.";
    ReportErrorToHal(hal_cli, HostError::kMessageTooLongError);
    return false;
  }
  if (cbor_->IsMalformedUtf8()) {
    ConfUiLog(ERROR) << "The prompt text appears to have incorrect UTF8 format";
    ReportErrorToHal(hal_cli, HostError::kIncorrectUTF8);
    return false;
  }
  if (!cbor_->IsOk()) {
    ConfUiLog(ERROR) << "Unknown Error in cbor implementation";
    ReportErrorToHal(hal_cli, HostError::kSystemError);
    return false;
  }

  if (!RenderDialog()) {
    // the confirmation UI is driven by a user app, not running from the start
    // automatically so that means webRTC should have been set up
    ConfUiLog(ERROR) << "Dialog is not rendered. However, it should."
                     << "No webRTC can't initiate any confirmation UI.";
    ReportErrorToHal(hal_cli, HostError::kUIError);
    return false;
  }
  start_time_ = std::make_unique<TimePoint>(std::move(Clock::now()));
  if (!SendAck(hal_cli, session_id_, true, "started")) {
    ConfUiLog(ERROR) << "Ack to kStart failed in I/O";
    return false;
  }
  state_ = MainLoopState::kInSession;
  return true;
}

bool Session::HandleInSession(SharedFD hal_cli, const FsmInput fsm_input,
                              const ConfUiMessage& conf_ui_msg) {
  auto invalid_input_handler = [&, this]() {
    ReportErrorToHal(hal_cli, HostError::kSystemError);
    ConfUiLog(ERROR) << "cmd " << ToString(fsm_input)
                     << " should not be handled in HandleInSession";
  };

  if (!IsUserInput(fsm_input)) {
    invalid_input_handler();
    return false;
  }

  const auto& user_input_msg =
      static_cast<const ConfUiSecureUserSelectionMessage&>(conf_ui_msg);
  const auto response = user_input_msg.GetResponse();
  if (response == UserResponse::kUnknown ||
      response == UserResponse::kUserAbort) {
    invalid_input_handler();
    return false;
  }
  const bool is_secure_input = user_input_msg.IsSecure();

  ConfUiLog(VERBOSE) << "In HandleInSession, session " << session_id_
                     << " is sending the user input " << ToString(fsm_input);

  bool is_success = false;
  if (response == UserResponse::kCancel) {
    // no need to sign
    is_success =
        SendResponse(hal_cli, session_id_, UserResponse::kCancel,
                     std::vector<std::uint8_t>{}, std::vector<std::uint8_t>{});
  } else {
    message_ = std::move(cbor_->GetMessage());
    auto message_opt = (is_secure_input ? Sign(message_) : TestSign(message_));
    if (!message_opt) {
      ReportErrorToHal(hal_cli, HostError::kSystemError);
      return false;
    }
    signed_confirmation_ = message_opt.value();
    is_success = SendResponse(hal_cli, session_id_, UserResponse::kConfirm,
                              signed_confirmation_, message_);
  }

  if (!is_success) {
    ConfUiLog(ERROR) << "I/O error in sending user response to HAL";
    return false;
  }
  state_ = MainLoopState::kWaitStop;
  return true;
}

bool Session::HandleWaitStop(SharedFD hal_cli, const FsmInput fsm_input) {
  if (IsUserInput(fsm_input)) {
    // ignore user input
    state_ = MainLoopState::kWaitStop;
    return true;
  }
  if (fsm_input == FsmInput::kHalStop) {
    ConfUiLog(VERBOSE) << "Handling Abort in kWaitStop.";
    ScheduleToTerminate();
    return true;
  }
  ReportErrorToHal(hal_cli, HostError::kSystemError);
  ConfUiLog(FATAL) << "In WaitStop, received wrong HAL command "
                   << ToString(fsm_input);
  return false;
}

}  // end of namespace confui
}  // end of namespace cuttlefish
