🐛 Fix broken change detection
[rhynodge.git] / src / main / java / net / pterodactylus / rhynodge / states / ComicState.java
1 /*
2  * rhynodge - ComicState.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.rhynodge.states;
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Set;
27 import javax.annotation.Nonnull;
28 import javax.annotation.Nullable;
29
30 import net.pterodactylus.rhynodge.Reaction;
31 import net.pterodactylus.rhynodge.states.ComicState.Comic;
32
33 import com.fasterxml.jackson.annotation.JsonProperty;
34 import com.google.common.collect.Lists;
35 import org.apache.commons.lang3.StringEscapeUtils;
36 import org.apache.commons.lang3.StringUtils;
37
38 import static java.lang.String.format;
39
40 /**
41  * {@link net.pterodactylus.rhynodge.State} that can store an arbitrary amout of
42  * {@link Comic}s.
43  *
44  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
45  */
46 public class ComicState extends AbstractState implements Iterable<Comic> {
47
48         @JsonProperty
49         private final List<Comic> comics = Lists.newArrayList();
50         private final Set<Comic> newComics = new HashSet<>();
51
52         @SuppressWarnings("unused")
53         // used for deserialization
54         private ComicState() {
55         }
56
57         public ComicState(Collection<Comic> allComics) {
58                 this.comics.addAll(allComics);
59         }
60
61         public ComicState(Collection<Comic> allComics, Collection<Comic> newComics) {
62                 this(allComics);
63                 this.newComics.addAll(newComics);
64         }
65
66         @Override
67         public boolean isEmpty() {
68                 return comics.isEmpty();
69         }
70
71         @Override
72         public boolean triggered() {
73                 return !newComics.isEmpty();
74         }
75
76         public List<Comic> comics() {
77                 return comics;
78         }
79
80         @Override
81         public Iterator<Comic> iterator() {
82                 return comics.iterator();
83         }
84
85         @Override
86         public String toString() {
87                 return format("ComicState[comics=%s]", comics());
88         }
89
90         @Nonnull
91         @Override
92         protected String summary(Reaction reaction) {
93                 return format("New Comic found for “%s!”", reaction.name());
94         }
95
96         @Nonnull
97         @Override
98         protected String plainText() {
99                 StringBuilder text = new StringBuilder();
100
101                 for (Comic newComic : newComics) {
102                         text.append("Comic Found: ").append(newComic.title()).append("\n\n");
103                         for (Strip strip : newComic) {
104                                 text.append("Image: ").append(strip.imageUrl()).append("\n");
105                                 if (!StringUtils.isBlank(strip.comment())) {
106                                         text.append("Comment: ").append(strip.comment()).append("\n");
107                                 }
108                         }
109                         text.append("\n\n");
110                 }
111
112                 return text.toString();
113         }
114
115         @Nullable
116         @Override
117         protected String htmlText() {
118                 StringBuilder html = new StringBuilder();
119                 html.append("<body>");
120
121                 for (Comic newComic : newComics) {
122                         generateComicHtml(html, newComic);
123                 }
124
125                 List<Comic> latestComics = new ArrayList<>(comics());
126                 Collections.reverse(latestComics);
127                 int comicCount = 0;
128                 for (Comic comic : latestComics) {
129                         if (newComics.contains(comic)) {
130                                 continue;
131                         }
132                         generateComicHtml(html, comic);
133                         if (++comicCount == 7) {
134                                 break;
135                         }
136                 }
137
138                 return html.append("</body>").toString();
139         }
140
141         private void generateComicHtml(StringBuilder html, Comic comic) {
142                 html.append("<h1>").append(StringEscapeUtils.escapeHtml4(comic.title())).append("</h1>\n");
143                 for (Strip strip : comic) {
144                         html.append("<div><img src=\"").append(StringEscapeUtils.escapeHtml4(strip.imageUrl()));
145                         html.append("\" alt=\"").append(StringEscapeUtils.escapeHtml4(strip.comment()));
146                         html.append("\" title=\"").append(StringEscapeUtils.escapeHtml4(strip.comment()));
147                         html.append("\"></div>\n");
148                         html.append("<div>").append(StringEscapeUtils.escapeHtml4(strip.comment())).append("</div>\n");
149                 }
150         }
151
152         /**
153          * Defines a comic.
154          *
155          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
156          */
157         public static class Comic implements Iterable<Strip> {
158
159                 @JsonProperty
160                 private final String title;
161
162                 @JsonProperty
163                 private final List<Strip> strips = Lists.newArrayList();
164
165                 public Comic(@JsonProperty("title") String title) {
166                         this.title = title;
167                 }
168
169                 public String title() {
170                         return title;
171                 }
172
173                 public List<Strip> strips() {
174                         return strips;
175                 }
176
177                 public Comic add(Strip strip) {
178                         strips.add(strip);
179                         return this;
180                 }
181
182                 @Override
183                 public Iterator<Strip> iterator() {
184                         return strips.iterator();
185                 }
186
187                 @Override
188                 public int hashCode() {
189                         return title.hashCode() ^ strips().hashCode();
190                 }
191
192                 @Override
193                 public boolean equals(Object object) {
194                         if (!(object instanceof Comic)) {
195                                 return false;
196                         }
197                         Comic comic = (Comic) object;
198                         return title().equals(comic.title()) && strips().equals(comic.strips());
199                 }
200
201                 @Override
202                 public String toString() {
203                         return format("Comic[title=%s,strips=%s]", title(), strips());
204                 }
205
206         }
207
208         /**
209          * A strip is a single image that belongs to a comic.
210          *
211          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
212          */
213         public static class Strip {
214
215                 @JsonProperty
216                 private final String imageUrl;
217
218                 @JsonProperty
219                 private final String comment;
220
221                 public Strip(@JsonProperty("imageUrl") String imageUrl, @JsonProperty("comment") String comment) {
222                         this.imageUrl = imageUrl;
223                         this.comment = comment;
224                 }
225
226                 public String imageUrl() {
227                         return imageUrl;
228                 }
229
230                 public String comment() {
231                         return comment;
232                 }
233
234                 @Override
235                 public int hashCode() {
236                         return imageUrl().hashCode() ^ comment().hashCode();
237                 }
238
239                 @Override
240                 public boolean equals(Object object) {
241                         if (!(object instanceof Strip)) {
242                                 return false;
243                         }
244                         Strip strip = (Strip) object;
245                         return imageUrl().equals(strip.imageUrl()) && comment().equals(strip.comment());
246                 }
247
248                 @Override
249                 public String toString() {
250                         return format("Strip[imageUrl=%s,comment=%s]", imageUrl(), comment());
251                 }
252
253         }
254
255 }