// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// 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 "cobalt/media/sandbox/fuzzer_app.h"

#include "base/files/file_util.h"
#include "base/logging.h"
#include "starboard/common/string.h"
#include "starboard/directory.h"

namespace cobalt {
namespace media {
namespace sandbox {

FuzzerApp::FuzzerApp() : number_of_iterations_(-1) {}

bool FuzzerApp::Init(int argc, char* argv[], double min_ratio,
                     double max_ratio) {
  file_entries_.clear();

  int initial_seed;
  if (ParseInitialSeedAndNumberOfIterations(argc, argv, &initial_seed)) {
    CollectFiles(argv[argc - 1], min_ratio, max_ratio, initial_seed);
  }
  return !file_entries_.empty() && number_of_iterations_ > 0;
}

void FuzzerApp::RunFuzzingLoop() {
  DCHECK_GT(number_of_iterations_, 0);

  for (int i = 0; i < number_of_iterations_; ++i) {
    for (FileEntries::iterator iter = file_entries_.begin();
         iter != file_entries_.end(); ++iter) {
      LOG(INFO) << "Fuzzing \"" << iter->first << "\" "
                << "with seed " << iter->second.fuzzer.seed();

      Fuzz(iter->first, iter->second.fuzzer.GetFuzzedContent());
      iter->second.fuzzer.AdvanceSeed();
    }
  }
}

const std::vector<uint8>& FuzzerApp::GetFileContent(
    const std::string& filename) const {
  FileEntries::const_iterator iter = file_entries_.find(filename);
  DCHECK(iter != file_entries_.end());
  return iter->second.file_content;
}

bool FuzzerApp::ParseInitialSeedAndNumberOfIterations(int argc, char* argv[],
                                                      int* initial_seed) {
  DCHECK(initial_seed);

  *initial_seed = ZzufFuzzer::kSeedForOriginalContent;

  if (argc != 3 && argc != 4) {
    LOG(ERROR) << "Usage: " << argv[0]
               << " [initial seed (non-negative integer)]"
               << " <number of iterations>"
               << " <file name|directory name contains files to be fuzzed>";
    LOG(ERROR) << "For example: " << argv[0] << " 200000 /data/video-files";
    LOG(ERROR) << "             " << argv[0] << " 115 200000 /data/video-files";
    return false;
  }

  if (argc == 3) {
    *initial_seed = ZzufFuzzer::kSeedForOriginalContent;
    number_of_iterations_ = SbStringParseSignedInteger(argv[1], NULL, 10);

    if (number_of_iterations_ <= 0) {
      LOG(ERROR) << "Invalid 'number of iterations' " << argv[1];
      return false;
    }
  } else {
    DCHECK_EQ(argc, 4);
    *initial_seed = SbStringParseSignedInteger(argv[1], NULL, 10);

    if (*initial_seed < 0) {
      LOG(ERROR) << "Invalid 'initial seed' " << argv[1];
      return false;
    }

    number_of_iterations_ = SbStringParseSignedInteger(argv[2], NULL, 10);

    if (number_of_iterations_ <= 0) {
      LOG(ERROR) << "Invalid 'number of iterations' " << argv[2];
      return false;
    }
  }

  return true;
}

void FuzzerApp::CollectFiles(const std::string& path_name, double min_ratio,
                             double max_ratio, int initial_seed) {
  file_entries_.clear();

  SbDirectory directory = SbDirectoryOpen(path_name.c_str(), NULL);
  if (!SbDirectoryIsValid(directory)) {
    // Assuming it is a file.
    AddFile(path_name, min_ratio, max_ratio, initial_seed);
    return;
  }

  SbDirectoryEntry entry;
  while (SbDirectoryGetNext(directory, &entry)) {
    std::string file_name = path_name + SB_FILE_SEP_STRING + entry.name;
    AddFile(file_name, min_ratio, max_ratio, initial_seed);
  }

  SbDirectoryClose(directory);
}

void FuzzerApp::AddFile(const std::string& file_name, double min_ratio,
                        double max_ratio, int initial_seed) {
  LOG(INFO) << "Loading " << file_name;

  std::string content;
  if (!base::ReadFileToString(base::FilePath(file_name), &content)) {
    LOG(ERROR) << "Failed to load file " << file_name;
    return;
  }
  if (content.empty()) {
    LOG(ERROR) << file_name << " is empty";
    return;
  }
  std::vector<uint8> uint8_content(content.begin(), content.end());
  std::vector<uint8> parsed_content =
      ParseFileContent(file_name, uint8_content);
  if (parsed_content.empty()) {
    return;
  }
  file_entries_.insert(
      std::make_pair(file_name, FileEntry(uint8_content, parsed_content,
                                          min_ratio, max_ratio, initial_seed)));
}

FuzzerApp::FileEntry::FileEntry(const std::vector<uint8>& file_content,
                                const std::vector<uint8>& fuzz_content,
                                double min_ratio, double max_ratio,
                                int initial_seed)
    : file_content(file_content),
      fuzzer(fuzz_content, min_ratio, max_ratio, initial_seed) {}

}  // namespace sandbox
}  // namespace media
}  // namespace cobalt
