/**
 * Copyright 2020 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.
 */

#define LOG_TAG "NN_RAND_MODEL"

#include <android-base/logging.h>
#include <jni.h>

#include <algorithm>
#include <fstream>
#include <memory>
#include <optional>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#include "GeneratedTestUtils.h"
#include "fuzzing/OperationManager.h"
#include "fuzzing/RandomGraphGenerator.h"
#include "fuzzing/RandomGraphGeneratorUtils.h"

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
  android::base::InitLogging(nullptr, android::base::LogdLogger());
  android::base::SetMinimumLogSeverity(android::base::INFO);
  return JNI_VERSION_1_6;
}

enum RandomModelExecutionResult {
  kSuccess = 0,
  kFailedCompilation,
  kFailedExecution,
  kFailedOtherNnApiCall,
  // The following conditions are for internal retry
  kInvalidModelGenerated,
  kUnsupportedModelGenerated
};

class FuzzerLogRAII {
 public:
  FuzzerLogRAII(const std::string& nnapiLogPath) {
    using android::nn::fuzzing_test::alignedString;
    using android::nn::fuzzing_test::Logger;
    using android::nn::fuzzing_test::LoggerStream;

    NN_FUZZER_LOG_WRITE_FATAL_TO_SYSLOG(LOG_TAG);

    mFuzzerLogOpen = false;
    if (!nnapiLogPath.empty()) {
      // Checking if we can write to target file
      std::ofstream os;
      os.open(nnapiLogPath);

      if (os.fail()) {
        LOG(ERROR) << "Opening file " << nnapiLogPath << " failed";
      } else {
        NN_FUZZER_LOG_INIT(nnapiLogPath);
        LOG(INFO) << "Logging NNAPI to file " << nnapiLogPath;
        mFuzzerLogOpen = true;
      }
    }
  }
  ~FuzzerLogRAII() {
    if (mFuzzerLogOpen) {
      using android::nn::fuzzing_test::alignedString;
      using android::nn::fuzzing_test::Logger;
      using android::nn::fuzzing_test::LoggerStream;

      NN_FUZZER_LOG_CLOSE;
    }
  }

 private:
  bool mFuzzerLogOpen;
};

std::vector<test_helper::TestOperationType> getOperationsInModel(
    const test_helper::TestModel& testModel) {
  std::vector<test_helper::TestOperationType> result;
  testModel.forEachSubgraph(
      [&result](const test_helper::TestSubgraph& subgraph) {
        for (const auto& operation : subgraph.operations) {
          result.push_back(operation.type);
        }
      });

  return result;
}

const ANeuralNetworksDevice* findDeviceByName(const char* deviceName) {
  if (!deviceName) return nullptr;

  std::string deviceNameStr(deviceName);
  uint32_t numDevices = 0;
  ANeuralNetworks_getDeviceCount(&numDevices);

  for (uint32_t i = 0; i < numDevices; i++) {
    ANeuralNetworksDevice* device = nullptr;
    const char* buffer = nullptr;
    int getDeviceResult = ANeuralNetworks_getDevice(i, &device);
    if (getDeviceResult != ANEURALNETWORKS_NO_ERROR) {
      LOG(ERROR) << "Unable to get NNAPI device " << i << ": "
                 << getDeviceResult;
      return nullptr;
    }

    int getDeviceNameResult = ANeuralNetworksDevice_getName(device, &buffer);
    if (getDeviceNameResult != ANEURALNETWORKS_NO_ERROR) {
      LOG(ERROR) << "Unable to get name of NNAPI device " << i << ": "
                 << getDeviceNameResult;
      return nullptr;
    }

    if (deviceNameStr == buffer) {
      return device;
    }
  }

  LOG(ERROR) << "No device with name " << deviceNameStr;
  return nullptr;
}

const ANeuralNetworksDevice* getNnApiReferenceDevice() {
  return findDeviceByName("nnapi-reference");
}

class RandomGraphGenerator {
 public:
  RandomGraphGenerator(const ANeuralNetworksDevice* device,
                       const std::string& deviceName,
                       const std::string& testName, uint32_t numOperations,
                       uint32_t dimensionRange, std::string nnapiLogPath,
                       std::string failedModelDumpPath)
      : mTestName(testName),
        mDevice(device),
        mDeviceName(deviceName),
        mNnApiReference(getNnApiReferenceDevice()),
        mSupportedOpsFilter(),
        mNumOperations(numOperations),
        mDimensionRange(dimensionRange),
        nnapiFuzzerLogRAII(nnapiLogPath),
        mFailedModelDumpPath(failedModelDumpPath) {}

  RandomModelExecutionResult init() {
    // Limiting the ops in the generator to a subset we know the target device
    // supports to avoid failing the test because we are unable to find a
    // suitable model to compile.
    RandomModelExecutionResult filterInitResult;
    filterInitResult =
        HalVersionsSupportedByDevice(&mSupportedOpsFilter.versions);
    if (filterInitResult != kSuccess) return filterInitResult;

    filterInitResult =
        OperandTypesSupportedByDevice(&mSupportedOpsFilter.dataTypes);
    if (filterInitResult != kSuccess) return filterInitResult;

    return OperationsSupportedByDevice(mSupportedOpsFilter,
                                       &mSupportedOpsFilter.opcodes);
  }

  RandomModelExecutionResult runRandomModel(bool compilationOnly) {
    using android::nn::generated_tests::createModel;
    using android::nn::generated_tests::createRequest;
    using android::nn::generated_tests::GeneratedModel;
    using android::nn::test_wrapper::Compilation;
    using android::nn::test_wrapper::Execution;
    using android::nn::wrapper::Result;

    std::optional<test_helper::TestModel> testModel =
        createRandomModel(mSupportedOpsFilter);
    if (!testModel) {
      LOG(ERROR) << mTestName << ": No model generated";
      return kInvalidModelGenerated;
    }

    GeneratedModel model;
    createModel(*testModel, &model);
    if (!model.isValid()) {
      LOG(ERROR) << mTestName << ": Randomly generated model is not valid";
      return kInvalidModelGenerated;
    }
    auto modelFinishResult = model.finish();
    if (modelFinishResult != Result::NO_ERROR) {
      LOG(ERROR) << mTestName << ": Failed to finish model, result is "
                 << static_cast<int>(modelFinishResult);
      return kInvalidModelGenerated;
    }

    bool fullySupportedModel = false;
    if (mDevice) {
      std::unique_ptr<bool[]> opsSupportedFlags =
          std::make_unique<bool[]>(mNumOperations);
      std::fill(opsSupportedFlags.get(),
                opsSupportedFlags.get() + mNumOperations, false);
      // Check if the device fully supports the graph.
      int supportedOpResult =
          ANeuralNetworksModel_getSupportedOperationsForDevices(
              model.getHandle(), &mDevice, 1, opsSupportedFlags.get());
      if (supportedOpResult != ANEURALNETWORKS_NO_ERROR) {
        return kFailedOtherNnApiCall;
      }

      // accepting the model even if partially supported since we found that it
      // is extremely difficult to have fully supported models.
      // We could consider a minimum number (or percentage of total number) of
      // operations to be supported to consider the model  acceptable. For the
      // moment we just accept any model that has any supported op.
      bool supported = std::any_of(opsSupportedFlags.get(),
                                   opsSupportedFlags.get() + mNumOperations,
                                   [](bool v) { return v; });
      if (!supported) {
        return kUnsupportedModelGenerated;
      }

      fullySupportedModel = std::all_of(
          opsSupportedFlags.get(), opsSupportedFlags.get() + mNumOperations,
          [](bool v) { return v; });
    }

    std::vector<const ANeuralNetworksDevice*> devices;
    if (mDevice) {
      devices.push_back(mDevice);
      if (!fullySupportedModel) {
        // If model is not fully supported we allow NNAPI to use reference
        // implementation. This is to avoid having this test constantly
        // nullified by the inability of finding a fully supported model.
        LOG(VERBOSE) << "Allowing model to be partially executed on NNAPI reference device";
        devices.push_back(mNnApiReference);
      }
    }

    auto [compilationResult, compilation] = CreateCompilation(model, devices);
    if (compilationResult != Result::NO_ERROR) {
      LOG(WARNING) << mTestName << ": Compilation preparation failed with result "
                   << static_cast<int>(compilationResult);

      dumpModel(*testModel);
      return kFailedCompilation;
    }
    compilationResult = compilation.finish();
    if (compilationResult != Result::NO_ERROR) {
      LOG(WARNING) << mTestName << ": Compilation failed with result "
                   << static_cast<int>(compilationResult);

      dumpModel(*testModel);
      return kFailedCompilation;
    }

    if (!compilationOnly) {
      Execution execution(&compilation);
      std::vector<test_helper::TestBuffer> outputs;
      createRequest(*testModel, &execution, &outputs);

      // Compute result.
      Result executeReturn = execution.compute();
      if (executeReturn != Result::NO_ERROR) {
        LOG(WARNING) << mTestName << ": Execution failed with result "
                     << static_cast<int>(executeReturn);

        dumpModel(*testModel);
        return kFailedExecution;
      }
    }

    return kSuccess;
  }

  const std::string mTestName;

 private:
  android::nn::fuzzing_test::RandomGraph mRandomGraph;
  std::random_device mSeedGenerator;
  const ANeuralNetworksDevice* mDevice;
  // empty string if mDevice is null
  const std::string mDeviceName;
  const ANeuralNetworksDevice* mNnApiReference;
  android::nn::fuzzing_test::OperationFilter mSupportedOpsFilter;
  const uint32_t mNumOperations;
  const uint32_t mDimensionRange;
  FuzzerLogRAII nnapiFuzzerLogRAII;
  const std::string mFailedModelDumpPath;

  std::optional<test_helper::TestModel> createRandomModel(
      const android::nn::fuzzing_test::OperationFilter& opFilter) {
    android::nn::fuzzing_test::OperationManager::get()->applyFilter(opFilter);

    auto seed = mSeedGenerator();
    if (!mRandomGraph.generate(seed, mNumOperations, mDimensionRange)) {
      return std::nullopt;
    }

    return {mRandomGraph.createTestModel()};
  }

  RandomModelExecutionResult HalVersionsSupportedByDevice(
      std::vector<test_helper::TestHalVersion>* result) {
    if (!mDevice) {
      return kSuccess;
    }

    int64_t featureLevel;
    auto getDeviceFeatureLevelResult =
        ANeuralNetworksDevice_getFeatureLevel(mDevice, &featureLevel);
    if (getDeviceFeatureLevelResult != ANEURALNETWORKS_NO_ERROR) {
      LOG(ERROR) << mTestName << ": Unable to query device feature level";
      return kFailedOtherNnApiCall;
    }

    if (featureLevel == 27) *result = {test_helper::TestHalVersion::V1_0};
    if (featureLevel == 28) *result = {test_helper::TestHalVersion::V1_1};
    if (featureLevel == 29) *result = {test_helper::TestHalVersion::V1_2};

    return kSuccess;
  }

  RandomModelExecutionResult OperandTypesSupportedByDevice(
      std::vector<test_helper::TestOperandType>* result) {
    if (!mDevice) {
      return kSuccess;
    }

    int32_t deviceType;
    auto getDeviceTypeResult =
        ANeuralNetworksDevice_getType(mDevice, &deviceType);
    if (getDeviceTypeResult != ANEURALNETWORKS_NO_ERROR) {
      LOG(ERROR) << mTestName << ": Unable to query device type";
      return kFailedOtherNnApiCall;
    }
    using test_helper::TestOperandType;
    switch (deviceType) {
      case ANEURALNETWORKS_DEVICE_GPU:
        // No quantized types
        *result = {
            TestOperandType::FLOAT32,        TestOperandType::INT32,
            TestOperandType::UINT32,         TestOperandType::TENSOR_FLOAT32,
            TestOperandType::TENSOR_INT32,   TestOperandType::BOOL,
            TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_BOOL8,
            TestOperandType::FLOAT16};
        break;
      case ANEURALNETWORKS_DEVICE_CPU:
      case ANEURALNETWORKS_DEVICE_ACCELERATOR:
        result->clear();  // no filter
        break;
      case ANEURALNETWORKS_DEVICE_UNKNOWN:
      case ANEURALNETWORKS_DEVICE_OTHER:
        if (mDeviceName.find("dsp") != std::string::npos) {
          *result = {TestOperandType::INT32,
                     TestOperandType::UINT32,
                     TestOperandType::TENSOR_INT32,
                     TestOperandType::BOOL,
                     TestOperandType::TENSOR_BOOL8,
                     TestOperandType::TENSOR_QUANT8_ASYMM,
                     TestOperandType::TENSOR_QUANT16_SYMM,
                     TestOperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
                     TestOperandType::TENSOR_QUANT16_ASYMM,
                     TestOperandType::TENSOR_QUANT8_SYMM,
                     TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED};
          break;
        }
        FALLTHROUGH_INTENDED;
      default:
        result->clear();  // no filter
    }
    return kSuccess;
  }

  /// Finds some operations supported by the device
  RandomModelExecutionResult OperationsSupportedByDevice(
      const android::nn::fuzzing_test::OperationFilter& basicFilter,
      std::vector<test_helper::TestOperationType>* result) {
    if (!mDevice) {
      return kSuccess;
    }

    constexpr int kNumOfAttempts = 50;
    std::set<test_helper::TestOperationType> supportedOps;
    for (int i = 0; i < kNumOfAttempts; i++) {
      std::optional<test_helper::TestModel> testModel =
          createRandomModel(basicFilter);
      if (!testModel) {
        LOG(ERROR)
            << mTestName
            << ": Unable to generate a model trying to understand the ops "
               "supported by target device";
        continue;
      }

      android::nn::generated_tests::GeneratedModel model;
      createModel(*testModel, &model);
      if (!model.isValid()) {
        LOG(WARNING) << mTestName << ": Randomly generated model is not valid";
        continue;
      }
      auto modelFinishResult = model.finish();
      if (modelFinishResult != android::nn::wrapper::Result::NO_ERROR) {
        LOG(WARNING) << "Model::finish call failed, result is "
                     << static_cast<int>(modelFinishResult);
        continue;
      }

      std::unique_ptr<bool[]> opsSupportedFlags =
          std::make_unique<bool[]>(mNumOperations);
      std::fill(opsSupportedFlags.get(),
                opsSupportedFlags.get() + mNumOperations, false);

      // Check if the device fully supports the graph.
      int supportedOpResult =
          ANeuralNetworksModel_getSupportedOperationsForDevices(
              model.getHandle(), &mDevice, 1, opsSupportedFlags.get());
      if (supportedOpResult != ANEURALNETWORKS_NO_ERROR) {
        return kFailedOtherNnApiCall;
      }

      std::vector<test_helper::TestOperationType> opsInModel =
          getOperationsInModel(*testModel);
      for (int opIndex = 0; opIndex < mNumOperations; opIndex++) {
        test_helper::TestOperationType currOp = opsInModel[opIndex];
        if (opsSupportedFlags[opIndex]) {
          supportedOps.insert(currOp);
        }
      }
    }
    std::copy(supportedOps.begin(), supportedOps.end(),
              std::back_inserter(*result));

    if (result->empty()) {
      LOG(WARNING)
          << mTestName
          << ": Could not find any operation supported by target device."
          << " Returning no filter.";
    } else {
      LOG(INFO) << mTestName << ": Filtering to " << result->size()
                << " supported operations";
    }

    return kSuccess;
  }

  void dumpModel(const test_helper::TestModel& testModel) {
    if (mFailedModelDumpPath.empty()) return;

    LOG(INFO) << mTestName << ": Dumping model failing tests to "
              << mFailedModelDumpPath;

    std::ofstream os(mFailedModelDumpPath);
    ASSERT_TRUE(os.is_open());
    os << "# Generated from " << mTestName << ". Do not edit.\n\n";
    test_helper::SpecDumper dumper(testModel, os);
    dumper.dumpTestModel();
  }

  std::pair<android::nn::wrapper::Result,
            android::nn::test_wrapper::Compilation>
  CreateCompilation(const android::nn::generated_tests::GeneratedModel& model,
                    const std::vector<const ANeuralNetworksDevice*>& devices) {
    using android::nn::test_wrapper::Compilation;
    if (!devices.empty())
      return Compilation::createForDevices(&model, devices);
    else
      return {android::nn::wrapper::Result::NO_ERROR, Compilation(&model)};
  }
};

extern "C" JNIEXPORT jint JNICALL
Java_com_android_nn_crashtest_core_RandomGraphTest_runRandomModel(
    JNIEnv* env, jclass /* static method */, jlong _generatorHandle,
    jboolean _compilationOnly, jlong _maxModelSearchTimeSeconds) {
  RandomGraphGenerator* graphGenerator =
      reinterpret_cast<RandomGraphGenerator*>(_generatorHandle);

  std::time_t startTime = std::time(nullptr);

  int result = kSuccess;
  int modelSearchAttempt = 0;
  while (std::difftime(std::time(nullptr), startTime) <
         _maxModelSearchTimeSeconds) {
    modelSearchAttempt++;

    result = graphGenerator->runRandomModel(_compilationOnly);

    // if by chance we generated an invalid model or a model that couldn't run
    // on the target accelerator we will try again.
    if (result != kInvalidModelGenerated &&
        result != kUnsupportedModelGenerated) {
      break;
    }
  }

  if (result == kInvalidModelGenerated ||
      result == kUnsupportedModelGenerated) {
    LOG(WARNING) << graphGenerator->mTestName
                 << ": Max time to search for a model of "
                 << static_cast<long>(_maxModelSearchTimeSeconds)
                 << "seconds reached. Aborting test at attempt "
                 << modelSearchAttempt;
  }

  return result;
}

extern "C" JNIEXPORT jlong JNICALL
com_android_nn_crashtest_core_RandomGraphTest_RandomGraphTest_createRandomGraphGenerator(
    JNIEnv* env, jclass /* static method */, jstring _nnApiDeviceName,
    jint _numOperations, jint _dimensionRange, jstring _testName,
    jstring _nnapiLogPath, jstring _failedModelDumpPath) {
  const char* nnApiDeviceName =
      _nnApiDeviceName ? env->GetStringUTFChars(_nnApiDeviceName, nullptr)
                       : nullptr;

  std::string nnApiDeviceNameStr{nnApiDeviceName ? nnApiDeviceName : ""};
  const ANeuralNetworksDevice* device = nullptr;
  if (nnApiDeviceName) {
    device = findDeviceByName(nnApiDeviceName);
    if (!device) {
      LOG(ERROR) << ": Unable to find accelerator " << nnApiDeviceName;
      env->ReleaseStringUTFChars(_nnApiDeviceName, nnApiDeviceName);
      return reinterpret_cast<jlong>(nullptr);
    }
    env->ReleaseStringUTFChars(_nnApiDeviceName, nnApiDeviceName);
  }

  std::string testName{"no-test-name"};
  if (_testName) {
    const char* testNameBuf = env->GetStringUTFChars(_testName, nullptr);
    testName = testNameBuf;
    env->ReleaseStringUTFChars(_testName, testNameBuf);
  }

  std::string nnapiLogPath;
  if (_nnapiLogPath) {
    const char* nnapiLogPathTmp =
        env->GetStringUTFChars(_nnapiLogPath, nullptr);
    nnapiLogPath = nnapiLogPathTmp;
    env->ReleaseStringUTFChars(_nnapiLogPath, nnapiLogPathTmp);
  }

  std::string failedModelDumpPath;
  if (_failedModelDumpPath) {
    const char* failedModelDumpPathTmp =
        env->GetStringUTFChars(_failedModelDumpPath, nullptr);
    failedModelDumpPath = failedModelDumpPathTmp;
    env->ReleaseStringUTFChars(_failedModelDumpPath, failedModelDumpPathTmp);
  }

  uint32_t numOperations = static_cast<uint32_t>(_numOperations);
  uint32_t dimensionRange = static_cast<uint32_t>(_dimensionRange);

  RandomGraphGenerator* result = new RandomGraphGenerator(
      device, nnApiDeviceNameStr, testName, numOperations, dimensionRange,
      nnapiLogPath, failedModelDumpPath);

  if (result->init() != kSuccess) {
    delete result;
    return reinterpret_cast<jlong>(nullptr);
  }

  return reinterpret_cast<jlong>(result);
}

extern "C" JNIEXPORT void JNICALL
com_android_nn_crashtest_core_RandomGraphTest_RandomGraphTest_destroyRandomGraphGenerator(
    JNIEnv* env, jclass /* static method */, jlong generatorHandle) {
  RandomGraphGenerator* graphGenerator =
      reinterpret_cast<RandomGraphGenerator*>(generatorHandle);
  delete graphGenerator;
}
