// Copyright 2018 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 <stdlib.h>

#include <limits>
#include <memory>
#include <utility>

#include <base/environment.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>

#include "vm_tools/garcon/icon_index_file.h"
#include "vm_tools/garcon/ini_parse_util.h"

namespace {
// Ridiculously large size for an icon index file.
constexpr size_t kMaxIconIndexFileSize = 10485760;  // 10 MB
// Name for the icon theme section we want.
constexpr char kIconThemeSectionName[] = "Icon Theme";
constexpr char kIconThemeName[] = "Name";
constexpr char kIconThemeNameWithLocale[] = "Name[";
constexpr char kIconThemeDirectories[] = "Directories";
constexpr char kIconThemeScaledDirectories[] = "ScaledDirectories";
constexpr char kDirectorySize[] = "Size";
constexpr char kDirectoryScale[] = "Scale";
constexpr char kDirectoryContext[] = "Context";
constexpr char kDirectoryType[] = "Type";
constexpr char kDirectoryMaxSize[] = "MaxSize";
constexpr char kDirectoryMinSize[] = "MinSize";
constexpr char kDirectoryThreshold[] = "Threshold";
// Icon directory types.
constexpr char kDirectoryTypeThreshold[] = "Threshold";
constexpr char kDirectoryTypeScalable[] = "Scalable";
// Valid types of directory entries in index files.
const char* const kValidDirectoryContexts[] = {"Applications", "MimeTypes"};
const char* const kValidDirectorySuffixes[] = {"apps", "mimetypes"};

// Max value for any integer in the file. Nothing should be large values outside
// of any reasonable pixel size/scale/threshold, nor should they be
// non-positive. This would be higher but we want to ensure squaring this number
// and multiplying by 100 doesn't violate the 32-bit max.
constexpr size_t kMaxReasonableValue = 4096;  // 4K
bool IsValueReasonable(int x) {
  return x > 0 && x < kMaxReasonableValue;
}

}  // namespace

namespace vm_tools {
namespace garcon {

// static
int IconIndexFile::Distance(const DirectoryEntry& directory_entry,
                            int search_size,
                            int search_scale) {
  int directory_scaled_size = directory_entry.size * directory_entry.scale;
  int search_scaled_size = search_size * search_scale;
  if (directory_scaled_size >= search_scaled_size) {
    return (directory_scaled_size - search_scaled_size) * 100 /
           search_scaled_size;
  } else {
    return (search_scaled_size - directory_scaled_size) * 100 /
           directory_scaled_size;
  }
}

// static
bool IconIndexFile::PerfectMatch(const DirectoryEntry& directory_entry,
                                 int search_size,
                                 int search_scale) {
  return directory_entry.size == search_size &&
         directory_entry.scale == search_scale;
}

// static
bool IconIndexFile::WithinLimit(const DirectoryEntry& directory_entry,
                                int search_size) {
  if (directory_entry.type == kDirectoryTypeThreshold) {
    if (search_size >= directory_entry.size) {
      return directory_entry.size * directory_entry.threshold >= search_size;
    } else {
      return search_size * directory_entry.threshold >= directory_entry.size;
    }
  } else if (directory_entry.type == kDirectoryTypeScalable) {
    return search_size >= directory_entry.min_size &&
           search_size <= directory_entry.max_size;
  } else {
    return search_size == directory_entry.size;
  }
}

// static
std::unique_ptr<IconIndexFile> IconIndexFile::ParseIconIndexFile(
    const base::FilePath& icon_dir) {
  std::unique_ptr<IconIndexFile> retval(new IconIndexFile(icon_dir));
  if (!retval->LoadFromFile(icon_dir.Append("index.theme"))) {
    retval.reset();
  }
  return retval;
}

std::vector<base::FilePath> IconIndexFile::GetPathsForSizeAndScale(
    int icon_size, int scale) {
  std::vector<base::FilePath> retval;
  std::multimap<int, const DirectoryEntry*> path_map;
  std::vector<base::FilePath> within_limit;
  std::vector<base::FilePath> the_rest;
  for (const auto& directory_entry : directory_entries_) {
    path_map.emplace(Distance(directory_entry, icon_size, scale),
                     &directory_entry);
  }
  for (const auto& path_element : path_map) {
    if (PerfectMatch(*path_element.second, icon_size, scale)) {
      retval.emplace_back(icon_dir_.Append(path_element.second->directory));
    } else if (WithinLimit(*path_element.second, icon_size * scale)) {
      within_limit.emplace_back(
          icon_dir_.Append(path_element.second->directory));
    } else {
      the_rest.emplace_back(icon_dir_.Append(path_element.second->directory));
    }
  }
  retval.insert(retval.end(), std::make_move_iterator(within_limit.begin()),
                std::make_move_iterator(within_limit.end()));
  retval.insert(retval.end(), std::make_move_iterator(the_rest.begin()),
                std::make_move_iterator(the_rest.end()));
  return retval;
}

bool IconIndexFile::CloseIconThemeSection(
    std::unique_ptr<IconThemeEntry> icon_theme_entry) {
  for (std::string& directory : icon_theme_entry->directories) {
    directories_.emplace(std::move(directory));
  }
  for (std::string& directory : icon_theme_entry->scaled_directories) {
    scaled_directories_.emplace(std::move(directory));
  }
  return true;
}

void IconIndexFile::FillInDefaultValues(DirectoryEntry* directory_entry) {
  if (directory_entry->type.empty()) {
    directory_entry->type = kDirectoryTypeThreshold;
  }
  if (directory_entry->max_size == 0) {
    directory_entry->max_size = directory_entry->size;
  }
  if (directory_entry->min_size == 0) {
    directory_entry->min_size = directory_entry->size;
  }
}

bool IconIndexFile::CloseDirectorySection(
    std::unique_ptr<DirectoryEntry> directory_entry) {
  const std::string& directory = directory_entry->directory;
  if (directories_.find(directory) == directories_.end() &&
      scaled_directories_.find(directory) == scaled_directories_.end()) {
    LOG(ERROR) << "Failed parsing icon index file due to directory section"
                  " name "
               << directory
               << " not appearing in icon theme section directories";
    return false;
  }

  // Make sure the values in this directory section are reasonable.
  if (!IsValueReasonable(directory_entry->scale) ||
      !IsValueReasonable(directory_entry->size) ||
      !IsValueReasonable(directory_entry->threshold)) {
    // Don't fail parsing the whole file, just don't add this directory.
    LOG(ERROR) << "Ignoring directory section \"" << directory
               << "\" in icon index file due to unreasonable value for scale, "
                  "size or threshold";
    return true;
  }

  bool valid_dir = false;
  for (const char* dir_context : kValidDirectoryContexts) {
    if (directory_entry->context == dir_context) {
      valid_dir = true;
      break;
    }
  }
  if (!valid_dir) {
    for (const char* dir_suffix : kValidDirectorySuffixes) {
      if (base::EndsWith(directory, dir_suffix, base::CompareCase::SENSITIVE)) {
        valid_dir = true;
        break;
      }
    }
  }
  if (valid_dir) {
    FillInDefaultValues(directory_entry.get());
    directory_entries_.emplace_back(std::move(*directory_entry));
  }
  return true;
}

bool IconIndexFile::LoadFromFile(const base::FilePath& file_path) {
  // Fail fast if the file doesn't exist, which can happen due to the number
  // of directories we are searching.
  if (!base::PathExists(file_path))
    return false;

  std::unique_ptr<IconThemeEntry> icon_theme_entry =
      std::make_unique<IconThemeEntry>();
  std::unique_ptr<DirectoryEntry> directory_entry =
      std::make_unique<DirectoryEntry>();

  enum ParsingPhase { start, icon_theme_section, directory_section };
  ParsingPhase parsing_phase = start;

  // First read in the file as a string.
  std::string icon_index_contents;
  if (!ReadFileToStringWithMaxSize(file_path, &icon_index_contents,
                                   kMaxIconIndexFileSize)) {
    LOG(ERROR) << "Failed reading icon index file: " << file_path.value();
    return false;
  }

  std::vector<base::StringPiece> icon_index_lines =
      base::SplitStringPiece(icon_index_contents, "\n", base::TRIM_WHITESPACE,
                             base::SPLIT_WANT_NONEMPTY);

  // Go through the file line by line.
  for (const auto& curr_line : icon_index_lines) {
    if (curr_line.front() == '#') {
      // Skip comment lines.
      continue;
    }
    if (curr_line.front() == '[') {
      // Section name.
      base::StringPiece section_name = ParseGroupName(curr_line);
      if (section_name.empty()) {
        continue;
      }
      if (parsing_phase == start) {
        if (section_name == kIconThemeSectionName) {
          parsing_phase = icon_theme_section;
        }
      } else if (parsing_phase == icon_theme_section) {
        if (!CloseIconThemeSection(std::move(icon_theme_entry))) {
          return false;
        }
        parsing_phase = directory_section;
        directory_entry->directory = section_name.as_string();
      } else if (parsing_phase == directory_section) {
        if (!CloseDirectorySection(std::move(directory_entry))) {
          return false;
        }
        directory_entry = std::make_unique<DirectoryEntry>();
        directory_entry->directory = section_name.as_string();
      }
    } else if (parsing_phase == start) {
      // We are before the icon theme section and this line doesn't begin that
      // entry so skip it.
      continue;
    } else {
      // Parse the key/value pair on this line.
      std::pair<std::string, std::string> key_value =
          ExtractKeyValuePair(curr_line);
      if (key_value.second.empty()) {
        // Invalid key/value pair since there was no delimiter, skip ths line.
        continue;
      }
      // Check for matching names against all the keys. For the ones that can
      // have a locale in the key name, do those last since we do a startsWith
      // comparison on those.
      std::string key = key_value.first;
      if (parsing_phase == icon_theme_section) {
        if (key == kIconThemeName) {
          icon_theme_entry->locale_name_map[""] =
              UnescapeString(key_value.second);
        } else if (key == kIconThemeDirectories) {
          ParseMultiString(key_value.second, &icon_theme_entry->directories,
                           ',');
        } else if (key == kIconThemeScaledDirectories) {
          ParseMultiString(key_value.second,
                           &icon_theme_entry->scaled_directories, ',');
        } else if (base::StartsWith(key, kIconThemeNameWithLocale,
                                    base::CompareCase::SENSITIVE)) {
          std::string locale = ExtractKeyLocale(key);
          if (locale.empty()) {
            continue;
          }
          icon_theme_entry->locale_name_map[locale] =
              UnescapeString(key_value.second);
        }
      } else if (parsing_phase == directory_section) {
        if (key == kDirectorySize) {
          base::StringToInt(key_value.second, &directory_entry->size);
        } else if (key == kDirectoryScale) {
          base::StringToInt(key_value.second, &directory_entry->scale);
        } else if (key == kDirectoryContext) {
          directory_entry->context = UnescapeString(key_value.second);
        } else if (key == kDirectoryType) {
          directory_entry->type = UnescapeString(key_value.second);
        } else if (key == kDirectoryMaxSize) {
          base::StringToInt(key_value.second, &directory_entry->max_size);
        } else if (key == kDirectoryMinSize) {
          base::StringToInt(key_value.second, &directory_entry->min_size);
        } else if (key == kDirectoryThreshold) {
          base::StringToInt(key_value.second, &directory_entry->threshold);
        }
      }
    }
  }

  if (parsing_phase != directory_section) {
    LOG(ERROR) << "Failed reading icon index file: " << file_path.value();
    return false;
  }
  if (!CloseDirectorySection(std::move(directory_entry))) {
    return false;
  }
  return true;
}

}  // namespace garcon
}  // namespace vm_tools
