package com.cellasoft.univrapp.model;
import android.net.Uri;
import android.provider.BaseColumns;
import android.util.Log;
import com.cellasoft.univrapp.Config;
import com.cellasoft.univrapp.UnivrReaderFactory;
import com.cellasoft.univrapp.loader.ChannelLoader;
import com.cellasoft.univrapp.manager.ContentManager;
import com.cellasoft.univrapp.manager.SynchronizationManager;
import com.cellasoft.univrapp.provider.Provider;
import com.cellasoft.univrapp.reader.UnivrReader;
import com.cellasoft.univrapp.rss.RSSFeed;
import com.cellasoft.univrapp.rss.RSSHandler.OnNewEntryCallback;
import com.cellasoft.univrapp.utils.ActiveList;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
import java.util.Observable;
public class Channel extends Observable implements ActionSupport, Serializable {
private static final long serialVersionUID = 6999952067033640004L;
public boolean updating = false;
public int id;
public int lecturerId;
public String url;
public String title;
public String description;
public String imageUrl;
public int unread;
public long updateTime;
public boolean isSelected;
public boolean starred;
public boolean mute = false;
private transient ActiveList<Item> items = new ActiveList<Item>();
private Object synRoot = new Object();
public Channel() {
this.id = 0;
this.lecturerId = 0;
this.updateTime = new Timestamp(System.currentTimeMillis()).getTime();
}
public Channel(int id) {
this.id = id;
this.lecturerId = 0;
this.updateTime = new Timestamp(System.currentTimeMillis()).getTime();
}
public Channel(String url) {
this("", url);
}
public Channel(String title, String url) {
this();
this.title = title;
this.url = url;
this.starred = true;
}
public Channel(int lecturerId, String title, String url, String imageUrl,
String description) {
this(title, url);
this.lecturerId = lecturerId;
this.imageUrl = imageUrl;
this.description = description;
}
public Channel(Channel channel) {
this.id = channel.id;
this.lecturerId = channel.lecturerId;
this.url = channel.url;
this.title = channel.title;
this.description = channel.description;
this.imageUrl = channel.imageUrl;
this.unread = channel.unread;
this.updateTime = channel.updateTime;
this.isSelected = channel.isSelected;
this.starred = channel.starred;
this.mute = channel.mute;
this.updating = channel.updating;
}
public static Channel findById(int id, ChannelLoader loader) {
return ContentManager.loadChannel(id, loader);
}
public static List<Channel> loadAllChannels(ChannelLoader loader) {
return ContentManager.loadAllChannels(loader);
}
public ActiveList<Item> getItems() {
synchronized (items) {
if (items == null) {
items = new ActiveList<Item>();
}
return items;
}
}
public void clearItems() {
getItems().clear();
}
public boolean existItem(Item item) {
return this.getItems().indexOf(item) >= 0;
}
public void addItem(Item item) {
item.channel = this;
synchronized (synRoot) {
ActiveList<Item> items = this.getItems();
if (items.indexOf(item) < 0) {
// find insert location
int position = 0;
for (Item currentItem : this.items) {
if (currentItem.updateTime < item.updateTime) {
// if (currentItem.pubDate.before(item.pubDate)) {
items.add(position, item);
return;
}
position++;
}
items.add(item);
}
}
}
public void addItem(int position, Item item) {
synchronized (synRoot) {
ActiveList<Item> items = this.getItems();
if (items.indexOf(item) < 0)
items.add(position, item);
}
}
public boolean isUpdating() {
synchronized (synRoot) {
return updating;
}
}
public List<Item> update(int maxItems) {
synchronized (synRoot) {
if (updating)
return null;
updating = true;
SynchronizationManager.getInstance().onSynchronizationStart(id);
this.setChanged();
this.notifyObservers(updating);
}
List<Item> newItems = updateItems(maxItems);
updateTime = new Timestamp(System.currentTimeMillis()).getTime();
save();
saveItems(newItems);
synchronized (synRoot) {
updating = false;
this.setChanged();
this.notifyObservers(updating);
}
return newItems;
}
protected List<Item> updateItems(int maxItems) {
int numberOfFetchedItems = 0;
RSSFeed feed = null;
try {
UnivrReader reader = UnivrReaderFactory.getUnivrReader();
while (true) {
feed = reader.fetchEntriesOfFeed(this, maxItems,
new OnNewEntryCallback() {
@Override
public void onNewEntry(Item item) {
if (item.exist()) {
throw new RuntimeException(
"Found exist item. Stop parsing "
+ Channel.this.title);
} else {
item.channel = Channel.this;
}
}
});
List<Item> entries = feed.getEntries();
long updateTime = System.currentTimeMillis();
for (int i = entries.size() - 1; i >= 0; i--) {
Item item = entries.get(i);
item.updateTime = updateTime++;
this.addItem(0, item);
}
numberOfFetchedItems += feed.getEntries().size();
if (numberOfFetchedItems >= maxItems
|| feed.getEntries().size() < Config.MAX_ITEMS_PER_FETCH) {
break;
}
try {
Thread.yield();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (RuntimeException e) {
e.printStackTrace();
Log.e("ERROR", e.getMessage());
} catch (Exception e) {
Log.e("ERROR", e.getMessage());
}
if (feed != null)
return feed.getEntries();
return null;
}
private int saveItems(List<Item> items) {
int newItems = 0;
if (items != null && !items.isEmpty()) {
if (exist()) {
for (Item item : items) {
if (item.save()) {
newItems++;
}
}
}
}
return newItems;
}
public boolean isEmpty() {
return this.getItems().size() == 0;
}
public int size() {
return getItems().size();
}
public int indexOf(Item item) {
return getItems().indexOf(item);
}
public void markChannelToStarred() {
ContentManager.markChannelToStarred(this);
}
public void unmarkChannelToStarred() {
ContentManager.unmarkChannelToStarred(this);
}
public void markChannelToMute() {
ContentManager.markChannelToMute(this);
}
public void unmarkChannelToMute() {
ContentManager.unmarkChannelToMute(this);
}
public boolean subscribe() {
if (!ContentManager.existChannel(this)) {
return save();
}
return false;
}
@Override
public boolean save() {
return ContentManager.saveChannel(this);
}
@Override
public void delete() {
this.clearItems();
ContentManager.deleteChannel(this);
}
@Override
public boolean exist() {
return ContentManager.existChannel(this);
}
public int clean() {
return ContentManager.cleanChannel(this);
}
public void loadLightweightItems() {
ContentManager.loadAllItemsOfChannel(this,
ContentManager.LIGHTWEIGHT_ITEM_LOADER);
}
public void loadFullItems() {
ContentManager.loadAllItemsOfChannel(this,
ContentManager.FULL_ITEM_LOADER);
}
@Override
public String toString() {
return String
.format("Channel [id=%s, title=%s, description=%s, url=%s, thumbnail=%s]",
id, title, description, url, imageUrl);
}
public static final class Channels implements BaseColumns {
public static final Uri CONTENT_URI = Uri.parse("content://"
+ Provider.AUTHORITY + "/channels");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.cellasoft.univrapp.provider.channels";
public static final String ID = "ID";
public static final String LECTURER_ID = "LECTURER_ID";
public static final String TITLE = "TITLE";
public static final String URL = "URL";
public static final String DESCRIPTION = "DESCRIPTION";
public static final String UPDATE_TIME = "UPDATE_TIME";
public static final String UNREAD = "UNREAD";
public static final String STARRED = "STARRED";
public static final String MUTE = "MUTE";
public static final String IMAGE_URL = "IMAGE_URL";
private Channels() {
}
}
}