001package net.filebot.web;
002
003import static java.util.Collections.*;
004
005import java.util.List;
006import java.util.Locale;
007import java.util.regex.Matcher;
008import java.util.regex.Pattern;
009
010import net.filebot.util.FunctionList;
011
012public class Movie extends SearchResult {
013
014        public static final int UNDEFINED = 0;
015
016        protected int year;
017        protected int imdbId;
018        protected int tmdbId;
019
020        // optional movie name language hint
021        protected String language;
022
023        public Movie() {
024                // used by deserializer
025        }
026
027        public Movie(int id, String name, String[] aliasNames, int year, int imdbId, int tmdbId, Locale locale) {
028                super(id, name, aliasNames);
029                this.year = year;
030                this.imdbId = imdbId;
031                this.tmdbId = tmdbId;
032                this.language = locale == null ? null : locale.toLanguageTag();
033        }
034
035        public Movie(Movie movie) {
036                super(movie.id, movie.name, movie.aliasNames);
037                this.year = movie.year;
038                this.imdbId = movie.imdbId;
039                this.tmdbId = movie.tmdbId;
040                this.language = movie.language;
041        }
042
043        public int getYear() {
044                return year;
045        }
046
047        public int getImdbId() {
048                return imdbId;
049        }
050
051        public int getTmdbId() {
052                return tmdbId;
053        }
054
055        public Locale getLanguage() {
056                return language == null ? null : Locale.forLanguageTag(language);
057        }
058
059        public String getNameWithYear() {
060                return toString(name, year);
061        }
062
063        @Override
064        public List<String> getEffectiveNames() {
065                if (name == null || name.length() == 0) {
066                        return emptyList();
067                }
068                if (aliasNames == null || aliasNames.length == 0) {
069                        return singletonList(toString(name, year));
070                }
071                return FunctionList.of(i -> {
072                        return i == 0 ? Movie.toString(name, year) : Movie.toString(aliasNames[i - 1], year);
073                }, 1 + aliasNames.length);
074        }
075
076        public List<String> getEffectiveNamesWithoutYear() {
077                return super.getEffectiveNames();
078        }
079
080        @Override
081        public boolean equals(Object object) {
082                if (object instanceof Movie) {
083                        Movie other = (Movie) object;
084
085                        if (tmdbId > 0 && other.tmdbId > 0) {
086                                return tmdbId == other.tmdbId;
087                        }
088                        if (imdbId > 0 && other.imdbId > 0) {
089                                return imdbId == other.imdbId;
090                        }
091
092                        return year == other.year && name.equals(other.name);
093                }
094
095                return false;
096        }
097
098        @Override
099        public Movie clone() {
100                return new Movie(id, name, aliasNames, year, imdbId, tmdbId, getLanguage());
101        }
102
103        @Override
104        public String toString() {
105                if (name != null && year > 0) {
106                        return toString(name, year);
107                }
108
109                if (tmdbId > 0) {
110                        return "TheMovieDB::" + tmdbId;
111                }
112
113                if (imdbId > 0) {
114                        return "IMDB::" + imdbId;
115                }
116
117                return super.toString();
118        }
119
120        public static Movie IMDB(int imdbId) {
121                return new Movie(imdbId, null, null, UNDEFINED, imdbId, UNDEFINED, null);
122        }
123
124        public static Movie IMDB(String name, int year, int imdbId) {
125                return new Movie(imdbId, name, null, year, imdbId, UNDEFINED, null);
126        }
127
128        public static Movie TMDB(int tmdbId) {
129                return new Movie(tmdbId, null, null, UNDEFINED, UNDEFINED, tmdbId, null);
130        }
131
132        public static Movie TMDB(String name, int year, int tmdbId) {
133                return new Movie(tmdbId, name, null, year, UNDEFINED, tmdbId, null);
134        }
135
136        public static Movie NameYear(String name, int year) {
137                return new Movie(UNDEFINED, name, null, year, UNDEFINED, UNDEFINED, null);
138        }
139
140        public static Movie ID(Integer tmdbId, Integer imdbId, String name, Integer year) {
141                if ((tmdbId != null && tmdbId > 0) || (imdbId != null && imdbId > 0) || (name != null && year != null && !name.isEmpty() && year > 0)) {
142                        int id = tmdbId != null && tmdbId > 0 ? tmdbId : imdbId != null && imdbId > 0 ? imdbId : UNDEFINED;
143                        return new Movie(id, name, null, year == null ? UNDEFINED : year, imdbId == null ? UNDEFINED : imdbId, tmdbId == null ? UNDEFINED : tmdbId, null);
144                }
145                return null;
146        }
147
148        private static final Pattern NAME_YEAR_PATTERN = Pattern.compile("(.+?)[ _.][(]?((?:19|20)\\d{2})[)]?");
149
150        public static Movie matchNameYear(String s) {
151                if (s == null || s.isEmpty()) {
152                        return null;
153                }
154
155                Matcher m = NAME_YEAR_PATTERN.matcher(s.trim());
156                if (m.matches()) {
157                        return Movie.NameYear(m.group(1).trim(), Integer.parseInt(m.group(2)));
158                }
159
160                return null;
161        }
162
163        public static String toString(String name, int year) {
164                return year > 0 ? name + " (" + year + ")" : name;
165        }
166
167}