/*
 * Copyright (C) 2022-2023 The LineageOS 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 <fcntl.h>
#include <libgen.h>
#include <unistd.h>

#include <android-base/properties.h>
#include <edify/expr.h>
#include <liblp/liblp.h>
#include <otautil/error_code.h>
#include <ziparchive/zip_archive.h>

Value *VerifyNoDowngradeFn(const char* name, State *state,
                             const std::vector<std::unique_ptr<Expr>>& argv) {
  int ret = 1;
  std::vector<std::string> args;

  if (argv.size() != 1 || !ReadArgs(state, argv, &args))
    return ErrorAbort(state, kArgsParsingFailure,
                      "%s() error parsing arguments", name);

  std::string blModel = android::base::GetProperty("ro.boot.em.model", "");
  std::string shortModel = blModel.substr(blModel.find("-") + 1, std::string::npos);
  std::string blVer = android::base::GetProperty("ro.boot.bootloader", "");
  if (blVer.length() >= shortModel.length() + 4
      && args[0].length() >= shortModel.length() + 4) { // <model>XXU<binary>
    std::string curBinary = blVer.substr(shortModel.length() + 3, 1);
    std::string newBinary = args[0].substr(shortModel.length() + 3, 1);
    if (newBinary.at(0) >= curBinary.at(0)) {
      ret = 0;
    }
  }

  return StringValue(std::to_string(ret));
}

Value *MarkHeaderBtFn(const char* name, State *state,
                        const std::vector<std::unique_ptr<Expr>>& argv) {
  int ret = 0;
  std::vector<std::string> args;
  const char* partition;
  uint32_t magicOffset;
  uint32_t numImages;
  uint32_t magic1;

  if(argv.size() < 4 || argv.size() > 4 || !ReadArgs(state, argv, &args))
    return ErrorAbort(state, kArgsParsingFailure,
                      "%s() error parsing arguments", name);

  partition = args[0].c_str();
  magicOffset = std::atoi(args[1].c_str());
  numImages = std::atoi(args[2].c_str());
  magic1 = std::atoi(args[3].c_str());

  int fd = open(partition, O_RDWR);
  if (fd < 0)
    return ErrorAbort(state, kFileOpenFailure,
                      "%s() failed to open %s", name, partition);

  magic1 = magic1 << (magicOffset * 8);
  numImages = numImages << (magicOffset * 8);
  write(fd, (char*)&magic1, sizeof(uint32_t));
  write(fd, (char*)&numImages, sizeof(uint32_t));
  close(fd);

  return StringValue(std::to_string(ret));
}

#define FILENAME_MAX_LEN 32

Value *WriteDataBtFn(const char* name, State *state,
                        const std::vector<std::unique_ptr<Expr>>& argv) {
  int ret = 0;
  std::vector<std::string> args;
  const char* file;
  const char* filename;
  const char* partition;
  uint32_t offset;
  uint32_t filesize;

  if(argv.size() < 4 || argv.size() > 4 || !ReadArgs(state, argv, &args))
    return ErrorAbort(state, kArgsParsingFailure,
                      "%s() error parsing arguments", name);

  file = args[0].c_str();
  filename = basename(file);
  partition = args[1].c_str();
  offset = std::atoi(args[2].c_str());
  filesize = std::atoi(args[3].c_str());

  int fd = open(partition, O_RDWR);
  if (fd < 0)
    return ErrorAbort(state, kFileOpenFailure,
                      "%s() failed to open %s", name, partition);

  char filename_padded[FILENAME_MAX_LEN] = { 0 };
  strcpy(&filename_padded[0], filename);

  lseek(fd, offset, SEEK_SET);
  write(fd, &filename_padded[0], FILENAME_MAX_LEN);
  write(fd, (char*)&filesize, sizeof(uint32_t));

  // write data
  ZipArchiveHandle za = state->updater->GetPackageHandle();
  ZipEntry64 entry;
  if (FindEntry(za, file, &entry) != 0) {
    return ErrorAbort(state, kPackageExtractFileFailure,
                      "%s() %s not found in package", name, file);
  }

  if (ExtractEntryToFile(za, &entry, fd))
    return ErrorAbort(state, kPackageExtractFileFailure,
                      "%s() failed to extract %s from package", name, file);

  close(fd);

  return StringValue(std::to_string(ret));
}

Value *RetrofitDynamicPartitionsFn(const char* /* name */, State *state,
                        const std::vector<std::unique_ptr<Expr>>& /* argv */) {
  int ret = 0;
  std::unique_ptr<android::fs_mgr::LpMetadata> pt;
  std::string super_partition = android::base::GetProperty("ro.boot.super_partition", "");

  if (super_partition.empty()) {
    return ErrorAbort(state, kVendorFailure,
                      "The current recovery does not seem to support dynamic partitions, please update.");
  }

  pt = android::fs_mgr::ReadMetadata(super_partition, 0);
  if (!pt) { // No dynamic partitions metadata yet - flashing initial metadata is required
    state->updater->UiPrint("Flashing initial dynamic partitions partition table...");

    pt = android::fs_mgr::ReadFromImageFile("/tmp/super_empty.img");
    if (!pt) {
      return ErrorAbort(state, kFileOpenFailure, "Failed to read /tmp/super_empty.img");
    }

    if (!android::fs_mgr::FlashPartitionTable(super_partition, *pt.get())) {
      return ErrorAbort(state, kSetMetadataFailure,
                        "Failed to flash partition table of super partition: %s.", super_partition.c_str());
    }
  }

  return StringValue(std::to_string(ret));
}

void Register_librecovery_updater_exynos9820() {
  RegisterFunction("exynos9820.verify_no_downgrade", VerifyNoDowngradeFn);
  RegisterFunction("exynos9820.mark_header_bt", MarkHeaderBtFn);
  RegisterFunction("exynos9820.write_data_bt", WriteDataBtFn);
  RegisterFunction("exynos9820.retrofit_dynamic_partitions", RetrofitDynamicPartitionsFn);
}
