/*
 * Copyright (C) 2019 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 "install/wipe_data.h"

#include <string.h>

#include <functional>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "install/snapshot_utils.h"
#include "otautil/dirutil.h"
#include "recovery_ui/ui.h"
#include "recovery_utils/logging.h"
#include "recovery_utils/roots.h"

constexpr const char* CACHE_ROOT = "/cache";
//constexpr const char* DATA_ROOT = "/data";
//constexpr const char* METADATA_ROOT = "/metadata";

static bool EraseVolume(const char* volume) {
  bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);

  // ui->SetBackground(RecoveryUI::ERASING);
  // ui->SetProgressType(RecoveryUI::INDETERMINATE);

  std::vector<saved_log_file> log_files;
  if (is_cache) {
    // If we're reformatting /cache, we load any past logs (i.e. "/cache/recovery/last_*") and the
    // current log ("/cache/recovery/log") into memory, so we can restore them after the reformat.
    log_files = ReadLogFilesToMemory();
  }

  // ui->Print("Formatting %s...\n", volume);

  ensure_path_unmounted(volume);

  int result = format_volume(volume);

  if (is_cache) {
    RestoreLogFilesAfterFormat(log_files);
  }

  return (result == 0);
}

bool WipeCache(const std::function<bool()>& confirm_func) {
  bool has_cache = volume_for_mount_point("/cache") != nullptr;
  if (!has_cache) {
    // ui->Print("No /cache partition found.\n");
    return false;
  }

  if (confirm_func && !confirm_func()) {
    return false;
  }

  // ui->Print("\n-- Wiping cache...\n");
  // ui->SetBackground(RecoveryUI::ERASING);
  // ui->SetProgressType(RecoveryUI::INDETERMINATE);

  bool success = EraseVolume("/cache");
  //ui->Print("Cache wipe %s.\n", success ? "complete" : "failed");
  return success;
}

bool WipeData() {
  // RecoveryUI* ui = device->GetUI();
  // ui->Print("\n-- Wiping data...\n");
  // ui->SetBackground(RecoveryUI::ERASING);
  // ui->SetProgressType(RecoveryUI::INDETERMINATE);

  // if (!FinishPendingSnapshotMerges(device)) {
  //   ui->Print("Unable to check update status or complete merge, cannot wipe partitions.\n");
  //   return false;
  // }

  //bool success = device->PreWipeData();
  bool success = true;
  //if (success) {
    //success &= EraseVolume(DATA_ROOT);
    //bool has_cache = volume_for_mount_point("/cache") != nullptr;
    //if (has_cache) {
    //  success &= EraseVolume(CACHE_ROOT);
   // }
    //if (volume_for_mount_point(METADATA_ROOT) != nullptr) {
      //success &= EraseVolume(METADATA_ROOT);
    //}
  //}
  //if (success) {
    //success &= device->PostWipeData();
  //}
  // ui->Print("Data wipe %s.\n", success ? "complete" : "failed");
  return success;
}
