// Copyright (c) 2012 The Chromium 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 "base/nix/mime_util_xdg.h"

#include <cstdlib>
#include <list>
#include <map>
#include <vector>

#include "base/environment.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/nix/xdg_util.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "base/third_party/xdg_mime/xdgmime.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"

#if defined(TOOLKIT_GTK)
#include <gtk/gtk.h>  // NOLINT

#include "base/message_loop.h"
#endif

namespace {

class IconTheme;

// None of the XDG stuff is thread-safe, so serialize all access under
// this lock.
base::LazyInstance<base::Lock>::Leaky
    g_mime_util_xdg_lock = LAZY_INSTANCE_INITIALIZER;

class MimeUtilConstants {
 public:
  typedef std::map<std::string, IconTheme*> IconThemeMap;
  typedef std::map<FilePath, base::Time> IconDirMtimeMap;
  typedef std::vector<std::string> IconFormats;

  // Specified by XDG icon theme specs.
  static const int kUpdateIntervalInSeconds = 5;

  static const size_t kDefaultThemeNum = 4;

  static MimeUtilConstants* GetInstance() {
    return Singleton<MimeUtilConstants>::get();
  }

  // Store icon directories and their mtimes.
  IconDirMtimeMap icon_dirs_;

  // Store icon formats.
  IconFormats icon_formats_;

  // Store loaded icon_theme.
  IconThemeMap icon_themes_;

  // The default theme.
  IconTheme* default_themes_[kDefaultThemeNum];

  base::TimeTicks last_check_time_;

#if defined(TOOLKIT_GTK)
  // This is set by DetectGtkTheme(). We cache it so that we can access the
  // theme name from threads that aren't allowed to call
  // gtk_settings_get_default().
  std::string gtk_theme_name_;
#endif

 private:
  MimeUtilConstants() {
    icon_formats_.push_back(".png");
    icon_formats_.push_back(".svg");
    icon_formats_.push_back(".xpm");

    for (size_t i = 0; i < kDefaultThemeNum; ++i)
      default_themes_[i] = NULL;
  }
  ~MimeUtilConstants();

  friend struct DefaultSingletonTraits<MimeUtilConstants>;

  DISALLOW_COPY_AND_ASSIGN(MimeUtilConstants);
};

// IconTheme represents an icon theme as defined by the xdg icon theme spec.
// Example themes on GNOME include 'Human' and 'Mist'.
// Example themes on KDE include 'crystalsvg' and 'kdeclassic'.
class IconTheme {
 public:
  // A theme consists of multiple sub-directories, like '32x32' and 'scalable'.
  class SubDirInfo {
   public:
    // See spec for details.
    enum Type {
      Fixed,
      Scalable,
      Threshold
    };
    SubDirInfo()
        : size(0),
          type(Threshold),
          max_size(0),
          min_size(0),
          threshold(2) {
    }
    size_t size;  // Nominal size of the icons in this directory.
    Type type;  // Type of the icon size.
    size_t max_size;  // Maximum size that the icons can be scaled to.
    size_t min_size;  // Minimum size that the icons can be scaled to.
    size_t threshold;  // Maximum difference from desired size. 2 by default.
  };

  explicit IconTheme(const std::string& name);

  ~IconTheme() {}

  // Returns the path to an icon with the name |icon_name| and a size of |size|
  // pixels. If the icon does not exist, but |inherits| is true, then look for
  // the icon in the parent theme.
  FilePath GetIconPath(const std::string& icon_name, int size, bool inherits);

  // Load a theme with the name |theme_name| into memory. Returns null if theme
  // is invalid.
  static IconTheme* LoadTheme(const std::string& theme_name);

 private:
  // Returns the path to an icon with the name |icon_name| in |subdir|.
  FilePath GetIconPathUnderSubdir(const std::string& icon_name,
                                  const std::string& subdir);

  // Whether the theme loaded properly.
  bool IsValid() {
    return index_theme_loaded_;
  }

  // Read and parse |file| which is usually named 'index.theme' per theme spec.
  bool LoadIndexTheme(const FilePath& file);

  // Checks to see if the icons in |info| matches |size| (in pixels). Returns
  // 0 if they match, or the size difference in pixels.
  size_t MatchesSize(SubDirInfo* info, size_t size);

  // Yet another function to read a line.
  std::string ReadLine(FILE* fp);

  // Set directories to search for icons to the comma-separated list |dirs|.
  bool SetDirectories(const std::string& dirs);

  bool index_theme_loaded_;  // True if an instance is properly loaded.
  // store the scattered directories of this theme.
  std::list<FilePath> dirs_;

  // store the subdirs of this theme and array index of |info_array_|.
  std::map<std::string, int> subdirs_;
  scoped_array<SubDirInfo> info_array_;  // List of sub-directories.
  std::string inherits_;  // Name of the theme this one inherits from.
};

IconTheme::IconTheme(const std::string& name)
  : index_theme_loaded_(false),
    info_array_(NULL) {
  base::ThreadRestrictions::AssertIOAllowed();
  // Iterate on all icon directories to find directories of the specified
  // theme and load the first encountered index.theme.
  MimeUtilConstants::IconDirMtimeMap::iterator iter;
  FilePath theme_path;
  MimeUtilConstants::IconDirMtimeMap* icon_dirs =
      &MimeUtilConstants::GetInstance()->icon_dirs_;
  for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) {
    theme_path = iter->first.Append(name);
    if (!file_util::DirectoryExists(theme_path))
      continue;
    FilePath theme_index = theme_path.Append("index.theme");
    if (!index_theme_loaded_ && file_util::PathExists(theme_index)) {
      if (!LoadIndexTheme(theme_index))
        return;
      index_theme_loaded_ = true;
    }
    dirs_.push_back(theme_path);
  }
}

FilePath IconTheme::GetIconPath(const std::string& icon_name, int size,
                                bool inherits) {
  std::map<std::string, int>::iterator subdir_iter;
  FilePath icon_path;

  for (subdir_iter = subdirs_.begin();
       subdir_iter != subdirs_.end();
       ++subdir_iter) {
    SubDirInfo* info = &info_array_[subdir_iter->second];
    if (MatchesSize(info, size) == 0) {
      icon_path = GetIconPathUnderSubdir(icon_name, subdir_iter->first);
      if (!icon_path.empty())
        return icon_path;
    }
  }
  // Now looking for the mostly matched.
  size_t min_delta_seen = 9999;

  for (subdir_iter = subdirs_.begin();
       subdir_iter != subdirs_.end();
       ++subdir_iter) {
    SubDirInfo* info = &info_array_[subdir_iter->second];
    size_t delta = MatchesSize(info, size);
    if (delta < min_delta_seen) {
      FilePath path = GetIconPathUnderSubdir(icon_name, subdir_iter->first);
      if (!path.empty()) {
        min_delta_seen = delta;
        icon_path = path;
      }
    }
  }

  if (!icon_path.empty() || !inherits || inherits_ == "")
    return icon_path;

  IconTheme* theme = LoadTheme(inherits_);
  // Inheriting from itself means the theme is buggy but we shouldn't crash.
  if (theme && theme != this)
    return theme->GetIconPath(icon_name, size, inherits);
  else
    return FilePath();
}

IconTheme* IconTheme::LoadTheme(const std::string& theme_name) {
  scoped_ptr<IconTheme> theme;
  MimeUtilConstants::IconThemeMap* icon_themes =
      &MimeUtilConstants::GetInstance()->icon_themes_;
  if (icon_themes->find(theme_name) != icon_themes->end()) {
    theme.reset((*icon_themes)[theme_name]);
  } else {
    theme.reset(new IconTheme(theme_name));
    if (!theme->IsValid())
      theme.reset();
    (*icon_themes)[theme_name] = theme.get();
  }
  return theme.release();
}

FilePath IconTheme::GetIconPathUnderSubdir(const std::string& icon_name,
                                           const std::string& subdir) {
  FilePath icon_path;
  std::list<FilePath>::iterator dir_iter;
  MimeUtilConstants::IconFormats* icon_formats =
      &MimeUtilConstants::GetInstance()->icon_formats_;
  for (dir_iter = dirs_.begin(); dir_iter != dirs_.end(); ++dir_iter) {
    for (size_t i = 0; i < icon_formats->size(); ++i) {
      icon_path = dir_iter->Append(subdir);
      icon_path = icon_path.Append(icon_name + (*icon_formats)[i]);
      if (file_util::PathExists(icon_path))
        return icon_path;
    }
  }
  return FilePath();
}

bool IconTheme::LoadIndexTheme(const FilePath& file) {
  FILE* fp = file_util::OpenFile(file, "r");
  SubDirInfo* current_info = NULL;
  if (!fp)
    return false;

  // Read entries.
  while (!feof(fp) && !ferror(fp)) {
    std::string buf = ReadLine(fp);
    if (buf == "")
      break;

    std::string entry;
    TrimWhitespaceASCII(buf, TRIM_ALL, &entry);
    if (entry.length() == 0 || entry[0] == '#') {
      // Blank line or Comment.
      continue;
    } else if (entry[0] == '[' && info_array_.get()) {
      current_info = NULL;
      std::string subdir = entry.substr(1, entry.length() - 2);
      if (subdirs_.find(subdir) != subdirs_.end())
        current_info = &info_array_[subdirs_[subdir]];
    }

    std::string key, value;
    std::vector<std::string> r;
    base::SplitStringDontTrim(entry, '=', &r);
    if (r.size() < 2)
      continue;

    TrimWhitespaceASCII(r[0], TRIM_ALL, &key);
    for (size_t i = 1; i < r.size(); i++)
      value.append(r[i]);
    TrimWhitespaceASCII(value, TRIM_ALL, &value);

    if (current_info) {
      if (key == "Size") {
        current_info->size = atoi(value.c_str());
      } else if (key == "Type") {
        if (value == "Fixed")
          current_info->type = SubDirInfo::Fixed;
        else if (value == "Scalable")
          current_info->type = SubDirInfo::Scalable;
        else if (value == "Threshold")
          current_info->type = SubDirInfo::Threshold;
      } else if (key == "MaxSize") {
        current_info->max_size = atoi(value.c_str());
      } else if (key == "MinSize") {
        current_info->min_size = atoi(value.c_str());
      } else if (key == "Threshold") {
        current_info->threshold = atoi(value.c_str());
      }
    } else {
      if (key.compare("Directories") == 0 && !info_array_.get()) {
        if (!SetDirectories(value)) break;
      } else if (key.compare("Inherits") == 0) {
        if (value != "hicolor")
          inherits_ = value;
      }
    }
  }

  file_util::CloseFile(fp);
  return info_array_.get() != NULL;
}

size_t IconTheme::MatchesSize(SubDirInfo* info, size_t size) {
  if (info->type == SubDirInfo::Fixed) {
    if (size > info->size)
      return size - info->size;
    else
      return info->size - size;
  } else if (info->type == SubDirInfo::Scalable) {
    if (size < info->min_size)
      return info->min_size - size;
    if (size > info->max_size)
      return size - info->max_size;
    return 0;
  } else {
    if (size + info->threshold < info->size)
      return info->size - size - info->threshold;
    if (size > info->size + info->threshold)
      return size - info->size - info->threshold;
    return 0;
  }
}

std::string IconTheme::ReadLine(FILE* fp) {
  if (!fp)
    return "";

  std::string result = "";
  const size_t kBufferSize = 100;
  char buffer[kBufferSize];
  while ((fgets(buffer, kBufferSize - 1, fp)) != NULL) {
    result += buffer;
    size_t len = result.length();
    if (len == 0)
      break;
    char end = result[len - 1];
    if (end == '\n' || end == '\0')
      break;
  }

  return result;
}

bool IconTheme::SetDirectories(const std::string& dirs) {
  int num = 0;
  std::string::size_type pos = 0, epos;
  std::string dir;
  while ((epos = dirs.find(',', pos)) != std::string::npos) {
    TrimWhitespaceASCII(dirs.substr(pos, epos - pos), TRIM_ALL, &dir);
    if (dir.length() == 0) {
      DLOG(WARNING) << "Invalid index.theme: blank subdir";
      return false;
    }
    subdirs_[dir] = num++;
    pos = epos + 1;
  }
  TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir);
  if (dir.length() == 0) {
    DLOG(WARNING) << "Invalid index.theme: blank subdir";
    return false;
  }
  subdirs_[dir] = num++;
  info_array_.reset(new SubDirInfo[num]);
  return true;
}

bool CheckDirExistsAndGetMtime(const FilePath& dir,
                               base::Time* last_modified) {
  if (!file_util::DirectoryExists(dir))
    return false;
  base::PlatformFileInfo file_info;
  if (!file_util::GetFileInfo(dir, &file_info))
    return false;
  *last_modified = file_info.last_modified;
  return true;
}

// Make sure |dir| exists and add it to the list of icon directories.
void TryAddIconDir(const FilePath& dir) {
  base::Time last_modified;
  if (!CheckDirExistsAndGetMtime(dir, &last_modified))
    return;
  MimeUtilConstants::GetInstance()->icon_dirs_[dir] = last_modified;
}

// For a xdg directory |dir|, add the appropriate icon sub-directories.
void AddXDGDataDir(const FilePath& dir) {
  if (!file_util::DirectoryExists(dir))
    return;
  TryAddIconDir(dir.Append("icons"));
  TryAddIconDir(dir.Append("pixmaps"));
}

// Add all the xdg icon directories.
void InitIconDir() {
  FilePath home = file_util::GetHomeDir();
  if (!home.empty()) {
      FilePath legacy_data_dir(home);
      legacy_data_dir = legacy_data_dir.AppendASCII(".icons");
      if (file_util::DirectoryExists(legacy_data_dir))
        TryAddIconDir(legacy_data_dir);
  }
  const char* env = getenv("XDG_DATA_HOME");
  if (env) {
    AddXDGDataDir(FilePath(env));
  } else if (!home.empty()) {
    FilePath local_data_dir(home);
    local_data_dir = local_data_dir.AppendASCII(".local");
    local_data_dir = local_data_dir.AppendASCII("share");
    AddXDGDataDir(local_data_dir);
  }

  env = getenv("XDG_DATA_DIRS");
  if (!env) {
    AddXDGDataDir(FilePath("/usr/local/share"));
    AddXDGDataDir(FilePath("/usr/share"));
  } else {
    std::string xdg_data_dirs = env;
    std::string::size_type pos = 0, epos;
    while ((epos = xdg_data_dirs.find(':', pos)) != std::string::npos) {
      AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos)));
      pos = epos + 1;
    }
    AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos)));
  }
}

void EnsureUpdated() {
  MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
  if (constants->last_check_time_.is_null()) {
    constants->last_check_time_ = base::TimeTicks::Now();
    InitIconDir();
    return;
  }

  // Per xdg theme spec, we should check the icon directories every so often
  // for newly added icons.
  base::TimeDelta time_since_last_check =
      base::TimeTicks::Now() - constants->last_check_time_;
  if (time_since_last_check.InSeconds() > constants->kUpdateIntervalInSeconds) {
    constants->last_check_time_ += time_since_last_check;

    bool rescan_icon_dirs = false;
    MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_;
    MimeUtilConstants::IconDirMtimeMap::iterator iter;
    for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) {
      base::Time last_modified;
      if (!CheckDirExistsAndGetMtime(iter->first, &last_modified) ||
          last_modified != iter->second) {
        rescan_icon_dirs = true;
        break;
      }
    }

    if (rescan_icon_dirs) {
      constants->icon_dirs_.clear();
      constants->icon_themes_.clear();
      InitIconDir();
    }
  }
}

// Find a fallback icon if we cannot find it in the default theme.
FilePath LookupFallbackIcon(const std::string& icon_name) {
  MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
  MimeUtilConstants::IconDirMtimeMap::iterator iter;
  MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_;
  MimeUtilConstants::IconFormats* icon_formats = &constants->icon_formats_;
  for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) {
    for (size_t i = 0; i < icon_formats->size(); ++i) {
      FilePath icon = iter->first.Append(icon_name + (*icon_formats)[i]);
      if (file_util::PathExists(icon))
        return icon;
    }
  }
  return FilePath();
}

// Initialize the list of default themes.
void InitDefaultThemes() {
  IconTheme** default_themes =
      MimeUtilConstants::GetInstance()->default_themes_;

  scoped_ptr<base::Environment> env(base::Environment::Create());
  base::nix::DesktopEnvironment desktop_env =
      base::nix::GetDesktopEnvironment(env.get());
  if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE3 ||
      desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4) {
    // KDE
    std::string kde_default_theme;
    std::string kde_fallback_theme;

    // TODO(thestig): Figure out how to get the current icon theme on KDE.
    // Setting stored in ~/.kde/share/config/kdeglobals under Icons -> Theme.
    default_themes[0] = NULL;

    // Try some reasonable defaults for KDE.
    if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE3) {
      // KDE 3
      kde_default_theme = "default.kde";
      kde_fallback_theme = "crystalsvg";
    } else {
      // KDE 4
      kde_default_theme = "default.kde4";
      kde_fallback_theme = "oxygen";
    }
    default_themes[1] = IconTheme::LoadTheme(kde_default_theme);
    default_themes[2] = IconTheme::LoadTheme(kde_fallback_theme);
  } else {
#if defined(TOOLKIT_GTK)
    // Assume it's Gnome and use GTK to figure out the theme.
    default_themes[1] = IconTheme::LoadTheme(
        MimeUtilConstants::GetInstance()->gtk_theme_name_);
    default_themes[2] = IconTheme::LoadTheme("gnome");
#endif
  }
  // hicolor needs to be last per icon theme spec.
  default_themes[3] = IconTheme::LoadTheme("hicolor");

  for (size_t i = 0; i < MimeUtilConstants::kDefaultThemeNum; i++) {
    if (default_themes[i] == NULL)
      continue;
    // NULL out duplicate pointers.
    for (size_t j = i + 1; j < MimeUtilConstants::kDefaultThemeNum; j++) {
      if (default_themes[j] == default_themes[i])
        default_themes[j] = NULL;
    }
  }
}

// Try to find an icon with the name |icon_name| that's |size| pixels.
FilePath LookupIconInDefaultTheme(const std::string& icon_name, int size) {
  EnsureUpdated();
  MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
  MimeUtilConstants::IconThemeMap* icon_themes = &constants->icon_themes_;
  if (icon_themes->empty())
    InitDefaultThemes();

  FilePath icon_path;
  IconTheme** default_themes = constants->default_themes_;
  for (size_t i = 0; i < MimeUtilConstants::kDefaultThemeNum; i++) {
    if (default_themes[i]) {
      icon_path = default_themes[i]->GetIconPath(icon_name, size, true);
      if (!icon_path.empty())
        return icon_path;
    }
  }
  return LookupFallbackIcon(icon_name);
}

MimeUtilConstants::~MimeUtilConstants() {
  for (size_t i = 0; i < kDefaultThemeNum; i++)
    delete default_themes_[i];
}

}  // namespace

namespace base {
namespace nix {

std::string GetFileMimeType(const FilePath& filepath) {
  if (filepath.empty())
    return std::string();
  base::ThreadRestrictions::AssertIOAllowed();
  base::AutoLock scoped_lock(g_mime_util_xdg_lock.Get());
  return xdg_mime_get_mime_type_from_file_name(filepath.value().c_str());
}

std::string GetDataMimeType(const std::string& data) {
  base::ThreadRestrictions::AssertIOAllowed();
  base::AutoLock scoped_lock(g_mime_util_xdg_lock.Get());
  return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL);
}

#if defined(TOOLKIT_GTK)
void DetectGtkTheme() {
  // If the theme name is already loaded, do nothing. Chrome doesn't respond
  // to changes in the system theme, so we never need to set this more than
  // once.
  if (!MimeUtilConstants::GetInstance()->gtk_theme_name_.empty())
    return;

  // We should only be called on the UI thread.
  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());

  gchar* gtk_theme_name;
  g_object_get(gtk_settings_get_default(),
               "gtk-icon-theme-name",
               &gtk_theme_name, NULL);
  MimeUtilConstants::GetInstance()->gtk_theme_name_.assign(gtk_theme_name);
  g_free(gtk_theme_name);
}
#endif

FilePath GetMimeIcon(const std::string& mime_type, size_t size) {
  base::ThreadRestrictions::AssertIOAllowed();
  std::vector<std::string> icon_names;
  std::string icon_name;
  FilePath icon_file;

  if (!mime_type.empty()) {
    base::AutoLock scoped_lock(g_mime_util_xdg_lock.Get());
    const char *icon = xdg_mime_get_icon(mime_type.c_str());
    icon_name = std::string(icon ? icon : "");
  }

  if (icon_name.length())
    icon_names.push_back(icon_name);

  // For text/plain, try text-plain.
  icon_name = mime_type;
  for (size_t i = icon_name.find('/', 0); i != std::string::npos;
       i = icon_name.find('/', i + 1)) {
    icon_name[i] = '-';
  }
  icon_names.push_back(icon_name);
  // Also try gnome-mime-text-plain.
  icon_names.push_back("gnome-mime-" + icon_name);

  // Try "deb" for "application/x-deb" in KDE 3.
  size_t x_substr_pos = mime_type.find("/x-");
  if (x_substr_pos != std::string::npos) {
    icon_name = mime_type.substr(x_substr_pos + 3);
    icon_names.push_back(icon_name);
  }

  // Try generic name like text-x-generic.
  icon_name = mime_type.substr(0, mime_type.find('/')) + "-x-generic";
  icon_names.push_back(icon_name);

  // Last resort
  icon_names.push_back("unknown");

  for (size_t i = 0; i < icon_names.size(); i++) {
    if (icon_names[i][0] == '/') {
      icon_file = FilePath(icon_names[i]);
      if (file_util::PathExists(icon_file))
        return icon_file;
    } else {
      icon_file = LookupIconInDefaultTheme(icon_names[i], size);
      if (!icon_file.empty())
        return icon_file;
    }
  }
  return FilePath();
}

}  // namespace nix
}  // namespace base
