content: package de.danoeh.antennapod.storage.database;
  
  import de.danoeh.antennapod.model.feed.FeedItem;
  import de.danoeh.antennapod.model.feed.FeedMedia;
  
  import java.text.DateFormat;
  import java.util.Locale;
  import org.apache.commons.lang3.StringUtils;
  
  /**
   * Publishers sometimes mess up their feed by adding episodes twice or by changing the ID of existing episodes.
   * This class tries to guess if publishers actually meant another episode,
   * even if their feed explicitly says that the episodes are different.
   */
  public class FeedItemDuplicateGuesser {
      public static boolean seemDuplicates(FeedItem item1, FeedItem item2) {
          if (sameAndNotEmpty(item1.getItemIdentifier(), item2.getItemIdentifier())) {
              return true;
          }
          FeedMedia media1 = item1.getMedia();
          FeedMedia media2 = item2.getMedia();
          if (media1 == null || media2 == null) {
              return false;
          }
          if (sameAndNotEmpty(media1.getStreamUrl(), media2.getStreamUrl())) {
              return true;
          }
          return titlesLookSimilar(item1, item2)
                  && datesLookSimilar(item1, item2)
                  && durationsLookSimilar(media1, media2)
                  && mimeTypeLooksSimilar(media1, media2);
      }
  
      public static boolean sameAndNotEmpty(String string1, String string2) {
          if (StringUtils.isEmpty(string1) || StringUtils.isEmpty(string2)) {
              return false;
          }
          return string1.equals(string2);
      }
  
      private static boolean datesLookSimilar(FeedItem item1, FeedItem item2) {
          if (item1.getPubDate() == null || item2.getPubDate() == null) {
              return false;
          }
          DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); // MM/DD/YY
          String dateOriginal = dateFormat.format(item2.getPubDate());
          String dateNew = dateFormat.format(item1.getPubDate());
          return StringUtils.equals(dateOriginal, dateNew); // Same date; time is ignored.
      }
  
      private static boolean durationsLookSimilar(FeedMedia media1, FeedMedia media2) {
          return Math.abs(media1.getDuration() - media2.getDuration()) < 10 * 60L * 1000L;
      }
  
      private static boolean mimeTypeLooksSimilar(FeedMedia media1, FeedMedia media2) {
          String mimeType1 = media1.getMimeType();
          String mimeType2 = media2.getMimeType();
          if (mimeType1 == null || mimeType2 == null) {
              return true;
          }
          if (mimeType1.contains("/") && mimeType2.contains("/")) {
              mimeType1 = mimeType1.substring(0, mimeType1.indexOf("/"));
              mimeType2 = mimeType2.substring(0, mimeType2.indexOf("/"));
          }
          return StringUtils.equals(mimeType1, mimeType2);
      }
  
      private static boolean titlesLookSimilar(FeedItem item1, FeedItem item2) {
          return sameAndNotEmpty(canonicalizeTitle(item1.getTitle()), canonicalizeTitle(item2.getTitle()));
      }
  
      public static String canonicalizeTitle(String title) {
          if (title == null) {
              return "";
          }
          return title
                  .trim()
                  .replace('“', '"')
                  .replace('”', '"')
                  .replace('„', '"')
                  .replace('—', '-');
      }
  }
  