001package net.filebot.web;
002
003import static java.util.Arrays.*;
004
005import java.io.Serializable;
006import java.util.ArrayList;
007import java.util.List;
008import java.util.Objects;
009
010public class Episode implements Serializable {
011
012        // base episode record
013        protected String seriesName;
014        protected Integer season;
015        protected Integer episode;
016        protected String title;
017
018        // absolute episode number
019        protected Integer absolute;
020
021        // special number
022        protected Integer special;
023
024        // episode airdate
025        protected SimpleDate airdate;
026        protected Integer runtime;
027
028        // unique identifier
029        protected Integer id;
030
031        // extended series metadata
032        protected String group;
033        protected SeriesInfo seriesInfo;
034
035        public Episode() {
036                // used by deserializer
037        }
038
039        public Episode(Episode other) {
040                this(other.seriesName, other.season, other.episode, other.title, other.absolute, other.special, other.airdate, other.runtime, other.id, other.group, other.seriesInfo);
041        }
042
043        public Episode(String seriesName, Integer season, Integer episode, String title) {
044                this(seriesName, season, episode, title, null, null, null, null, null, null, null);
045        }
046
047        public Episode(String seriesName, Integer season, Integer episode, String title, Integer absolute, Integer special, SimpleDate airdate, Integer runtime, Integer id, String group, SeriesInfo seriesInfo) {
048                this.seriesName = seriesName;
049                this.season = season;
050                this.episode = episode;
051                this.title = title;
052                this.absolute = absolute;
053                this.special = special;
054                this.airdate = airdate == null ? null : airdate.clone();
055                this.runtime = runtime;
056                this.id = id;
057                this.group = group;
058                this.seriesInfo = seriesInfo == null ? null : seriesInfo.clone();
059        }
060
061        public String getSeriesName() {
062                return seriesName;
063        }
064
065        public Integer getEpisode() {
066                return episode;
067        }
068
069        public Integer getSeason() {
070                return season;
071        }
072
073        public String getTitle() {
074                return title;
075        }
076
077        public Integer getAbsolute() {
078                return absolute;
079        }
080
081        public Integer getSpecial() {
082                return special;
083        }
084
085        public SimpleDate getAirdate() {
086                return airdate;
087        }
088
089        public Integer getRuntime() {
090                return runtime;
091        }
092
093        public Integer getId() {
094                return id;
095        }
096
097        public String getGroup() {
098                return group;
099        }
100
101        public SeriesInfo getSeriesInfo() {
102                return seriesInfo;
103        }
104
105        public List<String> getSeriesNames() {
106                List<String> names = new ArrayList<String>();
107                if (seriesName != null) {
108                        names.add(seriesName);
109                }
110                if (seriesInfo != null) {
111                        if (seriesInfo.name != null && !seriesInfo.name.equals(seriesName)) {
112                                names.add(seriesInfo.name);
113                        }
114                        if (seriesInfo.aliasNames != null) {
115                                names.addAll(asList(seriesInfo.aliasNames));
116                        }
117                }
118                return names;
119        }
120
121        @Override
122        public boolean equals(Object obj) {
123                if (obj instanceof Episode) {
124                        Episode other = (Episode) obj;
125                        // check if database id matches
126                        if (id != null && other.id != null) {
127                                return id.equals(other.id) && Objects.equals(seriesInfo, other.seriesInfo);
128                        }
129                        // check if episode record matches
130                        return isEquivalent(other);
131                }
132
133                return false;
134        }
135
136        @Override
137        public int hashCode() {
138                return id != null ? id : Objects.hash(season, episode, absolute, special, seriesName, title);
139        }
140
141        public boolean isEquivalent(Episode other) {
142                return Objects.equals(absolute, other.absolute) && Objects.equals(season, other.season) && Objects.equals(episode, other.episode) && Objects.equals(special, other.special) && Objects.equals(seriesName, other.seriesName) && Objects.equals(title, other.title) && Objects.equals(group, other.group);
143        }
144
145        @Override
146        public Episode clone() {
147                return new Episode(this);
148        }
149
150        public Episode number(Integer episode) {
151                return new Episode(getSeriesName(), null, episode, getTitle(), null, null, getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
152        }
153
154        public Episode number(Integer season, Integer episode) {
155                return new Episode(getSeriesName(), season, episode, getTitle(), null, null, getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
156        }
157
158        public Episode number(Integer season, Integer episode, Integer absolute) {
159                return new Episode(getSeriesName(), season, episode, getTitle(), absolute, null, getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
160        }
161
162        public Episode title(String title) {
163                return new Episode(getSeriesName(), getSeason(), getEpisode(), title, getAbsolute(), getSpecial(), getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
164        }
165
166        public Episode group(String group) {
167                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), getAirdate(), getRuntime(), getId(), group, getSeriesInfo());
168        }
169
170        public Episode absolute(Integer absolute) {
171                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), absolute, getSpecial(), getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
172        }
173
174        public Episode airdate(String date) {
175                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), SimpleDate.parse(date), getRuntime(), getId(), getGroup(), getSeriesInfo());
176        }
177
178        public Episode airdate(int year, int month, int day) {
179                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), SimpleDate.of(year, month, day), getRuntime(), getId(), getGroup(), getSeriesInfo());
180        }
181
182        public Episode runtime(Integer runtime) {
183                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), getAirdate(), runtime, getId(), getGroup(), getSeriesInfo());
184        }
185
186        public Episode derive(Integer season, Integer episode) {
187                return derive(getSeriesName(), season, episode, null, null, null);
188        }
189
190        public Episode derive(Integer absolute) {
191                return derive(getSeriesName(), null, absolute, null, absolute, null);
192        }
193
194        public Episode derive(String seriesName, Integer season, Integer episode, String title, Integer absolute, SimpleDate airdate) {
195                return new Episode(seriesName, season, episode, title, absolute, null, airdate, null, null, null, null);
196        }
197
198        public MappedEpisode map(Episode mapping) {
199                return new MappedEpisode(this, mapping);
200        }
201
202        public MappedEpisode map(List<Episode> mapping) {
203                switch (mapping.size()) {
204                        case 0:
205                                return null;
206                        case 1:
207                                return new MappedEpisode(this, mapping.get(0));
208                        default:
209                                return new MappedEpisode(this, new MultiEpisode(mapping));
210                }
211        }
212
213        @Override
214        public String toString() {
215                return EpisodeFormat.DEFAULT.format(this);
216        }
217
218}