//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2019 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#ifndef HASH_HPP
#define HASH_HPP

#include <QtGlobal>
#include <Config.hpp>
#include <Vertex.hpp>
#include <QString>
#include <utility>
#include <functional>
#include <boost/functional/hash.hpp>

// Add hash for unordered maps
namespace std 
{
  /** Hash pairs */
  template <typename T1, typename T2>
  struct hash<std::pair<T1, T2> >
  {
    size_t operator()(const std::pair<T1, T2> &v) const
    {
      std::size_t seed = 0;
      boost::hash_combine(seed, v.first);
      boost::hash_combine(seed, v.second);
      return seed;
    }
  };

  /** Hash vertex/cell pairs */
  template <typename T1, typename T2>
  struct hash<std::pair< mgx::Vertex<T1>, mgx::Vertex<T2> > >
  {
    size_t operator()(const std::pair<mgx::Vertex<T1>, mgx::Vertex<T2> > &v) const
    {
      std::size_t seed = 0;
      boost::hash_combine(seed, v.first.id());
      boost::hash_combine(seed, v.second.id());
      return seed;
    }
  };

  // Hash QString
  // BJL 2021-04-19: As of Qt 5.14, Qt itself defines std::hash<QString>.
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
  template <> struct hash<QString>
  {

    size_t operator()(const QString &s) const
    {
      int hash = 0, strlen = s.length(), i;
      QChar character;
      if (strlen == 0)
        return hash;
      for (i = 0; i < strlen; i++) {
        character = s.at(i);
        hash = (31 * hash) + (character.unicode());
      }
      return hash;
    }
  };
#endif // Qt version < 5.14
}
#endif
