001package net.filebot.web;
002
003import static java.util.Arrays.*;
004import static java.util.Collections.*;
005import static java.util.stream.Collectors.*;
006
007import java.io.Serializable;
008import java.net.URL;
009import java.util.Comparator;
010import java.util.List;
011import java.util.Locale;
012import java.util.Objects;
013import java.util.function.Predicate;
014import java.util.stream.Stream;
015
016public class Artwork implements Serializable {
017
018        protected String[] tags;
019        protected URL url;
020
021        protected String language;
022        protected Double rating;
023
024        public Artwork() {
025                // used by serializer
026        }
027
028        public Artwork(Stream<?> tags, URL url, Locale language, Double rating) {
029                this.tags = tags.filter(Objects::nonNull).map(Object::toString).toArray(String[]::new);
030                this.url = url;
031                this.language = language == null || language.getLanguage().isEmpty() ? null : language.getLanguage();
032                this.rating = rating;
033        }
034
035        public List<String> getTags() {
036                return unmodifiableList(asList(tags));
037        }
038
039        public URL getUrl() {
040                return url;
041        }
042
043        public Locale getLanguage() {
044                return language == null ? null : new Locale(language);
045        }
046
047        public double getRating() {
048                return rating == null ? 0 : rating;
049        }
050
051        public boolean has(Predicate<String> predicate) {
052                return stream(tags).anyMatch(predicate);
053        }
054
055        public boolean matches(Object... tags) {
056                if (tags == null || tags.length == 0) {
057                        return true;
058                }
059
060                return stream(tags).filter(Objects::nonNull).map(Object::toString).allMatch(tag -> {
061                        return has(tag::equalsIgnoreCase) || tag.equalsIgnoreCase(language);
062                });
063        }
064
065        @Override
066        public int hashCode() {
067                return url.hashCode();
068        }
069
070        @Override
071        public boolean equals(Object other) {
072                if (other instanceof Artwork) {
073                        Artwork artwork = (Artwork) other;
074                        return url.sameFile(artwork.url);
075                }
076                return false;
077        }
078
079        @Override
080        public String toString() {
081                return Stream.of(String.join("/", tags), language, rating, url).filter(Objects::nonNull).map(Object::toString).collect(joining(", ", "[", "]"));
082        }
083
084        public static Comparator<Artwork> ratingOrder() {
085                return Comparator.comparing(Artwork::getRating, reverseOrder());
086        }
087
088        public static Comparator<Artwork> languageOrder(Locale locale) {
089                return Comparator.comparingInt(a -> a.language == null ? 1 : locale.getLanguage().equals(a.language) ? 0 : 2);
090        }
091
092        public static Comparator<Artwork> relevanceOrder(Locale locale) {
093                Comparator<Artwork> c = languageOrder(locale);
094
095                if (!locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
096                        c = c.thenComparing(languageOrder(Locale.ENGLISH));
097                }
098
099                return c.thenComparing(ratingOrder());
100        }
101
102}