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