package allen.town.podcast.core.storage;

import android.text.TextUtils;
import allen.town.podcast.model.feed.FeedItem;
import allen.town.podcast.model.feed.FeedMedia;

import java.text.DateFormat;
import java.util.Locale;

/**
 * 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)
                && TextUtils.equals(media1.getMime_type(), media2.getMime_type());
    }

    private static boolean sameAndNotEmpty(String string1, String string2) {
        if (TextUtils.isEmpty(string1) || TextUtils.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 TextUtils.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 titlesLookSimilar(FeedItem item1, FeedItem item2) {
        return sameAndNotEmpty(canonicalizeTitle(item1.getTitle()), canonicalizeTitle(item2.getTitle()));
    }

    private static String canonicalizeTitle(String title) {
        if (title == null) {
            return "";
        }
        return title
                .trim()
                .replace('“', '"')
                .replace('”', '"')
                .replace('„', '"')
                .replace('—', '-');
    }
}
