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
126                        // check if database id matches
127                        if (id != null && other.id != null) {
128                                return id.equals(other.id) && Objects.equals(seriesInfo, other.seriesInfo);
129                        }
130
131                        // check if episode record matches
132                        return Objects.equals(season, other.season) && Objects.equals(episode, other.episode) && Objects.equals(absolute, other.absolute) && Objects.equals(special, other.special) && Objects.equals(seriesName, other.seriesName) && Objects.equals(title, other.title) && Objects.equals(group, other.group);
133                }
134
135                return false;
136        }
137
138        @Override
139        public int hashCode() {
140                return id != null ? id : Objects.hash(season, episode, absolute, special, seriesName, title);
141        }
142
143        @Override
144        public Episode clone() {
145                return new Episode(this);
146        }
147
148        public Episode number(Integer episode) {
149                return new Episode(getSeriesName(), null, episode, getTitle(), null, null, getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
150        }
151
152        public Episode number(Integer season, Integer episode) {
153                return new Episode(getSeriesName(), season, episode, getTitle(), null, null, getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
154        }
155
156        public Episode number(Integer season, Integer episode, Integer absolute) {
157                return new Episode(getSeriesName(), season, episode, getTitle(), absolute, null, getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
158        }
159
160        public Episode title(String title) {
161                return new Episode(getSeriesName(), getSeason(), getEpisode(), title, getAbsolute(), getSpecial(), getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
162        }
163
164        public Episode group(String group) {
165                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), getAirdate(), getRuntime(), getId(), group, getSeriesInfo());
166        }
167
168        public Episode absolute(Integer absolute) {
169                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), absolute, getSpecial(), getAirdate(), getRuntime(), getId(), getGroup(), getSeriesInfo());
170        }
171
172        public Episode airdate(String date) {
173                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), SimpleDate.parse(date), getRuntime(), getId(), getGroup(), getSeriesInfo());
174        }
175
176        public Episode airdate(int year, int month, int day) {
177                return new Episode(getSeriesName(), getSeason(), getEpisode(), getTitle(), getAbsolute(), getSpecial(), SimpleDate.of(year, month, day), getRuntime(), getId(), getGroup(), getSeriesInfo());
178        }
179
180        public Episode derive(Integer season, Integer episode) {
181                return derive(getSeriesName(), season, episode, null, null, null);
182        }
183
184        public Episode derive(Integer absolute) {
185                return derive(getSeriesName(), null, absolute, null, absolute, null);
186        }
187
188        public Episode derive(String seriesName, Integer season, Integer episode, String title, Integer absolute, SimpleDate airdate) {
189                return new Episode(seriesName, season, episode, title, absolute, null, airdate, null, null, null, null);
190        }
191
192        public MappedEpisode map(Episode mapping) {
193                return new MappedEpisode(this, mapping);
194        }
195
196        public MappedEpisode map(List<Episode> mapping) {
197                switch (mapping.size()) {
198                        case 0:
199                                return null;
200                        case 1:
201                                return new MappedEpisode(this, mapping.get(0));
202                        default:
203                                return new MappedEpisode(this, new MultiEpisode(mapping));
204                }
205        }
206
207        @Override
208        public String toString() {
209                return EpisodeFormat.DEFAULT.format(this);
210        }
211
212}