// Copyright 2020 The Chromium OS 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 "init/clobber_ui.h"

#include <inttypes.h>
#include <sys/ioctl.h>
#include <termios.h>

#include <string>
#include <utility>

#include <base/strings/stringprintf.h>

namespace {

bool MakeTTYRaw(const base::File& tty) {
  struct termios terminal_properties;
  if (tcgetattr(tty.GetPlatformFile(), &terminal_properties) != 0) {
    PLOG(WARNING) << "Getting properties of output TTY failed";
    return false;
  }

  cfmakeraw(&terminal_properties);
  if (tcsetattr(tty.GetPlatformFile(), TCSANOW, &terminal_properties) != 0) {
    PLOG(WARNING) << "Setting properties of output TTY failed";
    return false;
  }
  return true;
}

bool GetTerminalWidth(const base::File& terminal, int* width_out) {
  if (!width_out) {
    LOG(ERROR) << "width_out cannot be NULL";
    return false;
  }

  struct winsize window_size;
  int ret = ioctl(terminal.GetPlatformFile(), TIOCGWINSZ, &window_size);
  if (ret) {
    PLOG(ERROR) << "TIOCGWINSZ ioctl failed";
    return false;
  }

  *width_out = window_size.ws_col;
  return true;
}

// If |terminal_width| is non-zero, we will display a progress bar based
// on that width value. Otherwise, we will not display a progress bar.
std::string BuildUiString(int terminal_width,
                          const base::TimeDelta& elapsed,
                          double progress) {
  std::string elapsed_time =
      base::StringPrintf("%d:%02d:%02" PRIi64, elapsed.InHours(),
                         elapsed.InMinutes() % 60, elapsed.InSeconds() % 60);
  std::string percent_done = base::StringPrintf("%3.0f%%", progress * 100);

  // Determine how much space we would have for a progress bar in our terminal.
  int progress_bar_width = 0;
  if (terminal_width > 0) {
    // Subtract 2 for padding spaces and 2 for bounding brackets.
    progress_bar_width =
        terminal_width - elapsed_time.length() - percent_done.length() - 2 - 2;
  }

  // Only show a progress bar if we have space.
  if (progress_bar_width > 0) {
    std::string progress_bar(progress_bar_width * progress, '=');
    if (progress_bar.length() < progress_bar_width) {
      // If we haven't filled up the width, add a '>' to the end of the
      // progress bar and pad with zeros to fill the width.
      progress_bar += ">";
      progress_bar +=
          std::string(progress_bar_width - progress_bar.length(), ' ');
    }
    return elapsed_time + " [" + progress_bar + "] " + percent_done;
  } else {
    return elapsed_time + " " + percent_done;
  }
}

}  // namespace

ClobberUi::ClobberUi(base::File&& terminal)
    : terminal_(std::move(terminal)), mode_(kIdle) {
  if (!MakeTTYRaw(terminal_)) {
    LOG(ERROR) << "Failed to set terminal to raw mode.";
  }
}

bool ClobberUi::StartWipeUi(int64_t bytes_to_write) {
  if (!wipe_ui_thread_.is_null()) {
    LOG(ERROR) << "UI is already running.";
    return false;
  }
  mode_ = kWipeUi;

  base::AutoLock auto_lock(lock_);
  state_.running = true;
  state_.total_bytes_written = 0;
  state_.bytes_to_write = bytes_to_write;
  if (!base::PlatformThread::Create(0, this, &wipe_ui_thread_)) {
    LOG(ERROR) << "Failed to create wipe UI thread.";
    return false;
  }

  return true;
}

bool ClobberUi::UpdateWipeProgress(int64_t total_bytes_written) {
  base::AutoLock auto_lock(lock_);
  if (wipe_ui_thread_.is_null() || mode_ != kWipeUi || !state_.running) {
    LOG(ERROR) << "Cannot update progress, wipe UI is not running.";
    return false;
  }

  state_.total_bytes_written = total_bytes_written;
  return true;
}

bool ClobberUi::StopWipeUi() {
  if (wipe_ui_thread_.is_null()) {
    LOG(ERROR) << "Failed to stop wipe UI, thread is not running.";
    return false;
  }

  if (mode_ != kWipeUi) {
    LOG(ERROR) << "Failed to stop wipe UI, current UI is not a wipe UI.";
    return false;
  }

  {
    base::AutoLock auto_lock(lock_);
    if (!state_.running) {
      LOG(ERROR) << "Failed to stop wipe UI, wipe UI is already being stopped.";
      return false;
    }
    state_.running = false;
  }

  base::PlatformThread::Join(wipe_ui_thread_);
  wipe_ui_thread_ = base::PlatformThreadHandle();
  mode_ = kIdle;
  return true;
}

bool ClobberUi::ShowCountdownTimer(const base::TimeDelta& duration) {
  if (mode_ != kIdle) {
    LOG(ERROR) << "Failed to show countdown timer, UI is already in use.";
    return false;
  }
  mode_ = kCountdownUi;

  base::TimeTicks start_time = base::TimeTicks::Now();
  base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
  while (elapsed < duration) {
    base::TimeDelta remaining = duration - elapsed;
    std::string countdown =
        base::StringPrintf("%2d:%02" PRIi64 "\r", remaining.InMinutes(),
                           remaining.InSeconds() % 60);
    terminal_.WriteAtCurrentPos(countdown.c_str(), countdown.size());
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
    elapsed = base::TimeTicks::Now() - start_time;
  }

  mode_ = kIdle;
  return true;
}

// static
std::string ClobberUi::BuildUiStringForTest(int terminal_width,
                                            const base::TimeDelta& elapsed,
                                            double progress) {
  return BuildUiString(terminal_width, elapsed, progress);
}

void ClobberUi::ThreadMain() {
  base::TimeTicks start_time = base::TimeTicks::Now();
  base::AutoLock auto_lock(lock_);
  bool show_progress_bar = true;
  while (state_.running) {
    base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
    double progress =
        static_cast<double>(state_.total_bytes_written) / state_.bytes_to_write;

    int terminal_width = 0;
    if (show_progress_bar && !GetTerminalWidth(terminal_, &terminal_width)) {
      LOG(WARNING)
          << "Getting terminal width failed. No progress bar will be shown.";
      show_progress_bar = false;
    }
    std::string output = BuildUiString(terminal_width, elapsed, progress);

    terminal_.WriteAtCurrentPos("\r", 1);
    terminal_.WriteAtCurrentPos(output.c_str(), output.size());

    {
      base::AutoUnlock auto_unlock(lock_);
      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
    }
  }
}
