package io.github.xwz.base.api; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.raizlabs.android.dbflow.annotation.Column; import com.raizlabs.android.dbflow.annotation.PrimaryKey; import com.raizlabs.android.dbflow.annotation.Table; import com.raizlabs.android.dbflow.structure.BaseModel; import org.json.JSONArray; import org.json.JSONException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import io.github.xwz.base.Utils; import io.github.xwz.base.content.ContentManagerBase; @Table(databaseName = ContentDatabase.NAME) public class EpisodeBaseModel extends BaseModel implements Serializable { private static final String TAG = "EpisodeBaseModel"; @Column @PrimaryKey(autoincrement = true) public long DATA_ID; @Column public String DATA_TYPE; @Column public String DATA_COLLECTION_KEY; @Column public int DATA_COLLECTION_INDEX; @Column private String href; @Column private String seriesTitle; @Column private String channel; @Column private String thumbnail; @Column private String episodeHouseNumber; private Set<String> categories = new HashSet<>(); @Column public String categoriesSerialized; @Column private String title; @Column private int duration; @Column private String rating; @Column private int episodeCount; @Column private String description; @Column private String cover; @Column private boolean isFilm = false; @Column private String related; @Column private long expiry; @Column private long pubDate; private long resumePosition; private boolean recent; private Map<String, List<EpisodeBaseModel>> others = new HashMap<>(); public List<String> getCategories() { return new ArrayList<>(categories); } public void save() { updateCategoriesSerialized(); super.save(); } public void insert() { updateCategoriesSerialized(); super.insert(); } public void update() { updateCategoriesSerialized(); super.update(); } void unserialize() { if (categoriesSerialized != null) { JSONArray arr = parseArray(categoriesSerialized); if (arr != null) { for (int i = 0; i < arr.length(); i++) { try { addCategory(arr.getString(i)); } catch (JSONException e) { e.printStackTrace(); } } } } } private JSONArray parseArray(String content) { if (content != null && content.contains("[") && content.contains("]")) { try { return new JSONArray(content); } catch (JSONException e) { e.printStackTrace(); } } return null; } public void addCategory(String cat) { categories.add(cat); } public void setCategories(List<String> cats) { categories = new HashSet<>(cats); } private void updateCategoriesSerialized() { Gson gson = new GsonBuilder().create(); categoriesSerialized = gson.toJson(categories); } public String getDurationText() { if (getRating() != null) { return getRating() + ", " + Utils.formatMillis(getDuration() * 1000); } else { return Utils.formatMillis(getDuration() * 1000); } } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof EpisodeBaseModel)) return false; EpisodeBaseModel other = (EpisodeBaseModel) o; return other.getHref().equals(this.getHref()); } public void merge(EpisodeBaseModel ep) { this.href = ep.href == null ? this.href : ep.href; this.seriesTitle = ep.seriesTitle == null ? this.seriesTitle : ep.seriesTitle; this.channel = ep.channel == null ? this.channel : ep.channel; this.thumbnail = ep.thumbnail == null ? this.thumbnail : ep.thumbnail; this.episodeHouseNumber = ep.episodeHouseNumber == null ? this.episodeHouseNumber : ep.episodeHouseNumber; this.categories.addAll(ep.categories); this.title = ep.title == null ? this.title : ep.title; this.duration = ep.duration; this.rating = ep.rating == null ? this.rating : ep.rating; this.episodeCount = ep.episodeCount; this.description = ep.description == null ? this.description : ep.description; this.cover = ep.cover == null ? this.cover : ep.cover; this.isFilm = ep.isFilm; this.others = ep.others.size() == 0 ? this.others : new LinkedHashMap<>(ep.others); this.related = ep.related == null ? this.related : ep.related; this.expiry = ep.expiry == 0 ? this.expiry : ep.expiry; this.pubDate = ep.pubDate == 0 ? this.pubDate : ep.pubDate; } protected boolean hasOther(String key) { return others.containsKey(key); } public void setOtherEpisodes(Map<String, List<EpisodeBaseModel>> more) { others = more; } public void setOtherEpisodes(String key, List<EpisodeBaseModel> more) { others.put(key, more); } public Map<String, List<EpisodeBaseModel>> getOtherEpisodes() { LinkedHashMap<String, List<EpisodeBaseModel>> all = new LinkedHashMap<>(); for (Map.Entry<String, List<EpisodeBaseModel>> more : others().entrySet()) { List<EpisodeBaseModel> episodes = new ArrayList<>(more.getValue()); if (ContentManagerBase.OTHER_EPISODES.equals(more.getKey())) { Collections.sort(episodes, comparePubDate()); } all.put(more.getKey(), episodes); } return all; } protected Map<String, List<EpisodeBaseModel>> others() { return others; } private List<EpisodeBaseModel> getOtherEpisodes(String cat) { Map<String, List<EpisodeBaseModel>> all = getOtherEpisodes(); if (all.containsKey(cat)) { return all.get(cat); } return new ArrayList<>(); } protected Comparator<EpisodeBaseModel> comparePubDate() { return new Comparator<EpisodeBaseModel>() { @Override public int compare(EpisodeBaseModel lhs, EpisodeBaseModel rhs) { return (int) (lhs.pubDate - rhs.pubDate); } }; } protected Comparator<EpisodeBaseModel> compareTitle() { return new Comparator<EpisodeBaseModel>() { @Override public int compare(EpisodeBaseModel lhs, EpisodeBaseModel rhs) { return lhs.getTitle().compareTo(rhs.getTitle()); } }; } public List<String> getOtherEpisodeUrls(String cat) { List<String> urls = new ArrayList<>(); for (EpisodeBaseModel ep : getOtherEpisodes(cat)) { urls.add(ep.getHref()); } return urls; } public boolean hasOtherEpisodes() { return others.size() > 0; } public boolean matches(String query) { boolean found = false; if (getSeriesTitle() != null) { found = found || getSeriesTitle().toLowerCase().contains(query); } if (getTitle() != null) { found = found || getTitle().toLowerCase().contains(query); } return found; } public boolean hasCover() { return getIsFilm() && getCover() != null && getCover().length() > 0; } public String getSeriesTitle() { return seriesTitle; } public void setSeriesTitle(String seriesTitle) { this.seriesTitle = seriesTitle; } public String getHref() { return href; } public void setHref(String href) { this.href = href; } public String getChannel() { return channel; } public void setChannel(String channel) { this.channel = channel; } public String getThumbnail() { return thumbnail; } public void setThumbnail(String thumbnail) { this.thumbnail = thumbnail; } public String getEpisodeHouseNumber() { return episodeHouseNumber; } public void setEpisodeHouseNumber(String episodeHouseNumber) { this.episodeHouseNumber = episodeHouseNumber; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getDuration() { return duration; } public void setDuration(int duration) { this.duration = duration; } public String getRating() { return rating; } public void setRating(String rating) { this.rating = rating; } public int getEpisodeCount() { return episodeCount; } public void setEpisodeCount(int episodeCount) { this.episodeCount = episodeCount; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getCover() { return cover; } public void setCover(String cover) { this.cover = cover; } public boolean getIsFilm() { return isFilm; } public void setIsFilm(boolean film) { this.isFilm = film; } public String getRelated() { return related; } public void setRelated(String related) { this.related = related; } public String toString() { return "{" + getHref() + ":'" + getSeriesTitle() + "', '" + getTitle() + "', " + pubDate + "}"; } public long getExpiry() { return expiry; } public void setExpiry(long expiry) { this.expiry = expiry; } public long getResumePosition() { return resumePosition; } public void setResumePosition(long resumePosition) { this.resumePosition = resumePosition; } public int getProgress() { return Math.round(100 * (float) getResumePosition() / (getDuration() * 1000)); } public boolean isRecent() { return recent; } public void setRecent(boolean recent) { this.recent = recent; } public long getPubDate() { return pubDate; } public void setPubDate(long pubDate) { this.pubDate = pubDate; } }