public class EighthActivity implements Parcelable, Comparable<EighthActivity> {
	private int AID;
	private int BID;
	private int SID;
	private int memberCount;
	private int capacity;
	private String name;
	private String description;
	private String URL;
	private String[] sponsors;
	private String[] rooms;
	private boolean restricted;
	private boolean administrative;
	private boolean presign;
	private boolean bothblocks;
	private boolean sticky;
	private boolean special;
	private boolean cancelled;
	private boolean favorite;

	private boolean header;

	public EighthActivity(int AID, int BID, int SID, int memberCount, int capacity, String name,
	                      String description, String URL, String[] sponsors, String[] rooms,
	                      boolean restricted, boolean administrative, boolean presign,
	                      boolean bothblocks, boolean sticky, boolean special, boolean cancelled,
	                      boolean favorite) {
		this.AID = AID;
		this.BID = BID;
		this.SID = SID;
		this.memberCount = memberCount;
		this.capacity = capacity;
		this.name = name;
		if (description == null || description.isEmpty()) {
			this.description = "No description.";
		} else {
			this.description = description;
		}
		this.URL = URL;
		this.sponsors = sponsors;
		this.rooms = rooms;
		this.restricted = restricted;
		this.administrative = administrative;
		this.presign = presign;
		this.bothblocks = bothblocks;
		this.sticky = sticky;
		this.special = special;
		this.cancelled = cancelled;
		this.favorite = favorite;
	}

	// Create a header object
	public EighthActivity(String name, SignupAdapter.ActivityHeaderType headerType) {
		this.header = true;
		this.name = name;
		switch (headerType) {
			case FAVORITE:
				favorite = true;
				break;
			case SPECIAL:
				special = true;
				break;
			case GENERAL:
			default:
				break;
		}
	}

	public static class Builder {
		private int AID;
		private int BID;
		private int SID;
		private int memberCount;
		private int capacity;
		private String name;
		private String description;
		private String URL;
		private String[] sponsors;
		private String[] rooms;
		private boolean restricted;
		private boolean administrative;
		private boolean presign;
		private boolean bothblocks;
		private boolean sticky;
		private boolean special;
		private boolean cancelled;
		private boolean favorite;
		private EighthActivity activity;

		public Builder() {}

		public Builder(EighthActivity activity) {
			this.activity = activity;
		}

		public Builder AID(int AID) {
			this.AID = AID;
			return this;
		}

		public Builder BID(int BID) {
			this.BID = BID;
			return this;
		}

		public Builder SID(int SID) {
			this.SID = SID;
			return this;
		}

		public Builder memberCount(int memberCount) {
			this.memberCount = memberCount;
			return this;
		}

		public Builder capacity(int capacity) {
			this.capacity = capacity;
			return this;
		}

		public Builder name(String name) {
			this.name = name.trim();
			return this;
		}

		public Builder description(String description) {
			if (description.toLowerCase().equals("no description available")) {
				this.description = null;
			} else {
				this.description = description.trim();
			}
			return this;
		}

		public Builder URL(String URL) {
			this.URL = URL;
			return this;
		}

		public Builder sponsors(String[] sponsors) {
			this.sponsors = sponsors;
			return this;
		}

		public Builder rooms(String[] rooms) {
			this.rooms = rooms;
			return this;
		}

		public Builder administrative(boolean administrative) {
			this.administrative = administrative;
			return this;
		}

		public Builder restricted(boolean restricted) {
			this.restricted = restricted;
			return this;
		}

		public Builder presign(boolean presign) {
			this.presign = presign;
			return this;
		}

		public Builder bothblocks(boolean bothblocks) {
			this.bothblocks = bothblocks;
			return this;
		}

		public Builder sticky(boolean sticky) {
			this.sticky = sticky;
			return this;
		}

		public Builder special(boolean special) {
			this.special = special;
			return this;
		}

		public Builder cancelled(boolean cancelled) {
			this.cancelled = cancelled;
			return this;
		}

		public Builder favorite(boolean favorite) {
			this.favorite = favorite;
			return this;
		}

		public EighthActivity build() {
			if (activity == null) {
				return new EighthActivity(AID, BID, SID, memberCount, capacity, name, description, URL,
						sponsors, rooms, restricted, administrative, presign, bothblocks, sticky,
						special, cancelled, favorite);
			}
			if (this.administrative) {
				activity.administrative = this.administrative;
			}
			if (this.restricted) {
				activity.restricted = this.restricted;
			}
			if (this.presign) {
				activity.presign = this.presign;
			}
			if (this.bothblocks) {
				activity.bothblocks = this.bothblocks;
			}
			if (this.sticky) {
				activity.sticky = this.sticky;
			}
			if (this.special) {
				activity.special = this.special;
			}
			if (this.cancelled) {
				activity.cancelled = this.cancelled;
			}
			if (this.favorite) {
				activity.favorite = this.favorite;
			}
			if (this.description != null) {
				activity.description = this.description;
			}
			return activity;
		}
	}

	/**
	 * Check if activity has been selected
	 * @return true if activity is not selected
	 */
	public boolean isNull() {
		return AID == -1;
	}

	public int getAID() {
		return AID;
	}

	public int getBID() {
		return BID;
	}

	public int getSID() {
		return SID;
	}

	public String getName() {
		return name;
	}

	public String getDescription() {
		return description;
	}

	public boolean isRestricted() {
		return restricted;
	}

	public boolean isPresign() {
		return presign;
	}

	public boolean isBothblocks() {
		return bothblocks;
	}

	public boolean isSticky() {
		return sticky;
	}

	public boolean isSpecial() {
		return special;
	}

	public String[] getRoomsArray() {
		return rooms;
	}

	public String getRooms() {
		return Utils.join(rooms);
	}

	public String getRoomsNoDelim() {
		return Utils.join(rooms, "");
	}

	public boolean hasRooms() {
		return rooms != null && rooms.length > 0;
	}

	public String[] getSponsorsArray() {
		return sponsors;
	}

	public String getSponsors() {
		return Utils.join(sponsors);
	}

	public String getSponsorsNoDelim() {
		return Utils.join(sponsors, "");
	}

	public boolean hasSponsors() {
		return !(sponsors == null || sponsors.length == 0 || sponsors[0].equals("CANCELLED"));
	}

	public boolean isCancelled() {
		return cancelled;
	}

	public boolean isFavorite() {
		return favorite;
	}

	public int getMemberCount() {
		return memberCount;
	}

	public int getCapacity() {
		return capacity;
	}

	public boolean isHeader() {
		return header;
	}

	public boolean hasDescription() {
		return !(description == null || description.equals("No description."));
	}

	public boolean isFull() {
		return capacity > 0 && memberCount >= capacity;
	}

	public boolean changeFavorite() {
		return favorite = !favorite;
	}

	public int compareTo(@NonNull EighthActivity other) {
		// Compare by name if both or neither are favorites, or return the favorite
		if (favorite) {
			if (other.favorite) {
				return name.compareToIgnoreCase(other.name);
			}
			return -1;
		}
		if (other.favorite) {
			return 1;
		}

		// Check for special
		if (!(special ^ other.special)) {
			return name.compareToIgnoreCase(other.name);
		}
		if (special) {
			return -1;
		}
		return 1;
	}

	protected EighthActivity(Parcel in) {
		AID = in.readInt();
		BID = in.readInt();
		SID = in.readInt();
		memberCount = in.readInt();
		capacity = in.readInt();
		name = in.readString();
		description = in.readString();
		URL = in.readString();
		sponsors = in.createStringArray();
		rooms = in.createStringArray();
		restricted = in.readByte() != 0;
		administrative = in.readByte() != 0;
		presign = in.readByte() != 0;
		bothblocks = in.readByte() != 0;
		sticky = in.readByte() != 0;
		special = in.readByte() != 0;
		cancelled = in.readByte() != 0;
		favorite = in.readByte() != 0;
		header = in.readByte() != 0;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(AID);
		dest.writeInt(BID);
		dest.writeInt(SID);
		dest.writeInt(memberCount);
		dest.writeInt(capacity);
		dest.writeString(name);
		dest.writeString(description);
		dest.writeString(URL);
		dest.writeStringArray(sponsors);
		dest.writeStringArray(rooms);
		dest.writeByte((byte) (restricted ? 1 : 0));
		dest.writeByte((byte) (administrative ? 1 : 0));
		dest.writeByte((byte) (presign ? 1 : 0));
		dest.writeByte((byte) (bothblocks ? 1 : 0));
		dest.writeByte((byte) (sticky ? 1 : 0));
		dest.writeByte((byte) (special ? 1 : 0));
		dest.writeByte((byte) (cancelled ? 1 : 0));
		dest.writeByte((byte) (favorite ? 1 : 0));
		dest.writeByte((byte) (header ? 1 : 0));
	}

	public static final Parcelable.Creator<EighthActivity> CREATOR = new Parcelable.Creator<EighthActivity>() {
		@Override
		public EighthActivity createFromParcel(Parcel in) {
			return new EighthActivity(in);
		}

		@Override
		public EighthActivity[] newArray(int size) {
			return new EighthActivity[size];
		}
	};
} public class EighthBlock implements Parcelable {
	private static final DateFormat DATE_FORMAT = new SimpleDateFormat("EEEE, MMMM d", Locale.US);
	private EighthActivity activity;
	private Date date;
	private int BID;
	private char type;
	private boolean locked;
	private boolean header;

	// Constructor for a header item
	public EighthBlock(Date date) {
		header = true;
		this.date = date;
	}

	public EighthBlock(Date date, int BID, char type, boolean locked) {
		this.date = date;
		this.BID = BID;
		this.type = type;
		this.locked = locked;
	}

	public static class Builder {
		private Date date;
		private int BID;
		private char type;
		private boolean locked;

		public Builder date(Date date) {
			this.date = date;
			return this;
		}

		public Builder BID(int BID) {
			this.BID = BID;
			return this;
		}

		public Builder type(char type) {
			this.type = type;
			return this;
		}

		public Builder locked(boolean locked) {
			this.locked = locked;
			return this;
		}

		public EighthBlock build() {
			return new EighthBlock(date, BID, type, locked);
		}
	}

	public void setEighth(EighthActivity activity) {
		this.activity = activity;
	}

	public EighthActivity getEighth() {
		return activity;
	}

	// No setter for ActivityItem - use setters for inner item

	public Date getDate() {
		return date;
	}

	public int getBID() {
		return BID;
	}

	public char getBlock() {
		return type;
	}

	public boolean isLocked() {
		return locked;
	}

	public boolean isHeader() {
		return header;
	}

	public Spannable getDisp() {
		// Add postfix
		String str = DATE_FORMAT.format(date);
		if (str.charAt(str.length() - 2) == '1') {
			str += "th";
		} else {
			switch (str.charAt(str.length() - 1)) {
				case '1':
					str += "st";
					break;
				case '2':
					str += "nd";
					break;
				case '3':
					str += "rd";
					break;
				default:
					str += "th";
			}
		}
		// Format postfix into superscript
		Spannable sp = new SpannableString(str);
		sp.setSpan(new SuperscriptSpan(), sp.length() - 2, sp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
		sp.setSpan(new RelativeSizeSpan(.75f), sp.length() - 2, sp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

		return sp;
	}

	protected EighthBlock(Parcel in) {
		activity = in.readParcelable(EighthActivity.class.getClassLoader());
		long tmpDate = in.readLong();
		date = tmpDate != -1 ? new Date(tmpDate) : null;
		BID = in.readInt();
		type = (char) in.readByte();
		locked = in.readByte() != 0;
		header = in.readByte() != 0;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeParcelable(activity, flags);
		dest.writeLong(date != null ? date.getTime() : -1L);
		dest.writeInt(BID);
		dest.writeByte((byte) type);
		dest.writeByte((byte) (locked ? 1 : 0));
		dest.writeByte((byte) (header ? 1 : 0));
	}

	public static final Parcelable.Creator<EighthBlock> CREATOR = new Parcelable.Creator<EighthBlock>() {
		@Override
		public EighthBlock createFromParcel(Parcel in) {
			return new EighthBlock(in);
		}

		@Override
		public EighthBlock[] newArray(int size) {
			return new EighthBlock[size];
		}
	};
} public class NewsPost implements Parcelable {
	private String URL;
	private int ID;
	private String title;
	private String content;
	private String author;
	private int user;
	private Date added;
	private Date updated;
	private String dateString;

	public NewsPost(String URL, int ID, String title, String content, String author, int user,
	                Date added, Date updated, String dateString) {
		this.URL = URL;
		this.ID = ID;
		this.title = title;
		this.content = content;
		this.author = author;
		this.user = user;
		this.added = added;
		this.updated = updated;
		this.dateString = dateString;
	}

	public static class Builder {
		private static final DateFormat FORMAT = new SimpleDateFormat("M/d/yy", Locale.US);
		private String URL;
		private int ID;
		private String title;
		private String content;
		private String author;
		private int user;
		private Date added;
		private Date updated;

		public Builder URL(String URL) {
			this.URL = URL;
			return this;
		}

		public Builder ID(int ID) {
			this.ID = ID;
			return this;
		}

		public Builder title(String title) {
			this.title = fix(title);
			if (this.title.isEmpty()) {
				this.title = "<i>Untitled</i>";
			}
			return this;
		}

		public Builder content(String content) {
			this.content = fix(content);
			if (this.content.isEmpty()) {
				this.content = "<i>No content</i>";
			}
			return this;
		}

		public Builder author(String author) {
			this.author = author;
			return this;
		}

		public Builder user(int user) {
			this.user = user;
			return this;
		}

		public Builder added(Date added) {
			this.added = added;
			return this;
		}

		public Builder updated(Date updated) {
			this.updated = updated;
			return this;
		}

		/**
		 * Fix unusual characters present in news
		 *
		 * @param malformedString Raw string from API request
		 * @return Cleaned string
		 */
		private String fix(String malformedString) {
			return malformedString.replace("â€“", ":")
					.replace("â€™", "&#39;")
					.replaceAll("(â€.|Â)", "")
					.trim();
		}

		public NewsPost build() {
			final String dateString;
			if (added.equals(updated)) {
				dateString = "Posted on " + FORMAT.format(added);
			} else {
				dateString = "Updated on " + FORMAT.format(updated);
			}
			return new NewsPost(URL, ID, title, content, author, user, added, updated, dateString);
		}
	}

	public String getURL() {
		return URL;
	}

	public int getID() {
		return ID;
	}

	public Spanned getTitle() {
		return Html.fromHtml(title);
	}

	public String getContent() {
		return content;
	}

	public Spanned getTrimmedContent() {
		return Html.fromHtml(content.replaceAll("(\\s{2}|<br\\s?/>)", " ").trim());
	}

	public String getAuthor() {
		return author;
	}

	public int getUser() {
		return user;
	}

	public Date getAdded() {
		return added;
	}

	public Date getUpdated() {
		return updated;
	}

	public String getDateString() {
		return dateString;
	}

	protected NewsPost(Parcel in) {
		URL = in.readString();
		ID = in.readInt();
		title = in.readString();
		content = in.readString();
		author = in.readString();
		user = in.readInt();
		added = new Date(in.readLong());
		updated = new Date(in.readLong());
		dateString = in.readString();
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(URL);
		dest.writeInt(ID);
		dest.writeString(title);
		dest.writeString(content);
		dest.writeString(author);
		dest.writeInt(user);
		dest.writeLong(added.getTime());
		dest.writeLong(updated.getTime());
		dest.writeString(dateString);
	}

	public static final Parcelable.Creator<NewsPost> CREATOR = new Parcelable.Creator<NewsPost>() {
		@Override
		public NewsPost createFromParcel(Parcel in) {
			return new NewsPost(in);
		}

		@Override
		public NewsPost[] newArray(int size) {
			return new NewsPost[size];
		}
	};
} public class Schedule implements Parcelable, Comparable<Schedule> {
	private String day;
	private Date date;
	private String type;
	private String blocks;
	private String times;

	private static final DateFormat mFormat = new SimpleDateFormat("EEE, MMM. d", Locale.US);

	/**
	 * @param day       Date (e.g. Monday, February 29)
	 * @param type      Day color (e.g. Blue)
	 * @param blocks    Names of the blocks
	 * @param times     Time intervals for blocks
	 */
	public Schedule(String day, Date date, String type, String blocks, String times) {
		this.day = day;
		this.date = date;
		this.type = type;
		this.blocks = blocks;
		this.times = times;
	}

	public static class Builder {
		private String day;
		private Date date;
		private String type;
		private String blocks;
		private String times;

		public Builder date(Date date) {
			this.date = date;
			this.day = mFormat.format(date);
			return this;
		}

		public Builder type(String type) {
			this.type = type.replace("<br>", "\n");
			return this;
		}

		public Builder blocks(String blocks) {
			this.blocks = blocks;
			return this;
		}

		public Builder times(String times) {
			this.times = times;
			return this;
		}

		public Schedule build() {
			return new Schedule(day, date, type, blocks, times);
		}
	}

	public String getDay() {
		return day;
	}

	public Date getDate() {
		return date;
	}

	public String getType() {
		return type;
	}

	public String getBlocks() {
		return blocks;
	}

	public String getTimes() {
		return times;
	}

	@Override
	public int compareTo(@NonNull Schedule schedule) {
		return date.compareTo(schedule.date);
	}

	protected Schedule(Parcel in) {
		day = in.readString();
		date = new Date(in.readLong());
		type = in.readString();
		blocks = in.readString();
		times = in.readString();
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(day);
		dest.writeLong(date.getTime());
		dest.writeString(type);
		dest.writeString(blocks);
		dest.writeString(times);
	}

	public static final Parcelable.Creator<Schedule> CREATOR = new Parcelable.Creator<Schedule>() {
		@Override
		public Schedule createFromParcel(Parcel in) {
			return new Schedule(in);
		}

		@Override
		public Schedule[] newArray(int size) {
			return new Schedule[size];
		}
	};
} public class User implements Parcelable {
	private String mUID; // UID is an integer, but only used as a string
	private String mUsername;
	private String[] mName;
	private Address mAddress;
	private String[] mEmails;
	private String mMobile;
	private int mGradYear;
	private Bitmap mPicture;

	public User(String UID, String username, String[] name, Address address, String[] emails,
	            String mobile, int gradYear, Bitmap picture) {
		this.mUID = UID;
		this.mUsername = username;
		this.mName = name;
		this.mAddress = address;
		this.mEmails = emails;
		this.mMobile = mobile;
		this.mGradYear = gradYear;
		this.mPicture = picture;
	}

	public static class Builder {
		private String UID;
		private String username;
		private String[] name;
		private Address address;
		private String[] emails;
		private String mobile;
		private int gradYear;
		private Bitmap picture;

		public Builder() {
			this.address = new Address(Locale.ENGLISH);
			this.name = new String[]{"", "", ""};
		}

		public Builder(User user) {
			this.UID = user.getUID();
			this.username = user.getUsername();
			this.name = user.getName();
			this.address = user.getAddress();
			this.emails = user.getEmails();
			this.mobile = user.getMobile();
			this.gradYear = user.getGradYear();
			this.picture = user.getPicture();
		}

		public Builder UID(String UID) {
			this.UID = UID;
			return this;
		}

		public Builder username(String username) {
			this.username = username;
			return this;
		}

		public Builder firstName(String first) {
			if (first != null) {
				this.name[0] = first;
			}
			return this;
		}

		public Builder middleName(String middle) {
			if (middle != null) {
				this.name[1] = middle;
			}
			return this;
		}

		public Builder lastName(String last) {
			if (last != null) {
				this.name[2] = last;
			}
			return this;
		}

		public Builder street(String street) {
			this.address.setAddressLine(0, street);
			return this;
		}

		public Builder city(String city) {
			this.address.setSubAdminArea(city);
			return this;
		}

		public Builder state(String state) {
			this.address.setAdminArea(state);
			return this;
		}

		public Builder postalCode(String postalCode) {
			this.address.setPostalCode(postalCode);
			return this;
		}

		public Builder emails(String[] emails) {
			this.emails = emails;
			return this;
		}

		public Builder phone(String home) {
			this.address.setPhone(home);
			return this;
		}

		public Builder mobile(String mobile) {
			this.mobile = mobile;
			return this;
		}

		public Builder gradYear(int gradYear) {
			this.gradYear = gradYear;
			return this;
		}

		public Builder picture(Bitmap picture) {
			this.picture = picture;
			return this;
		}

		public User build() {
			return new User(UID, username, name, address, emails, mobile, gradYear, picture);
		}
	}

	public String getUID() {
		return mUID;
	}

	public String getUsername() {
		return mUsername;
	}

	public String[] getName() {
		return mName;
	}

	public String getFullName() {
		return mName[0] + " " + mName[1] + " " + mName[2];
	}

	public String getShortName() {
		return mName[0] + " " + mName[2];
	}

	public Address getAddress() {
		return mAddress;
	}

	public String getAddressString() {
		return mAddress.getAddressLine(0) + "\n" +
				mAddress.getSubAdminArea() + ", " + mAddress.getAdminArea() + " " + mAddress.getPostalCode();
	}

	public String getPhone() {
		return mAddress.getPhone();
	}

	public String[] getEmails() {
		return mEmails;
	}

	public String getMobile() {
		return mMobile;
	}

	public int getGradYear() {
		return mGradYear;
	}

	public Bitmap getPicture() {
		return mPicture;
	}

	protected User(Parcel in) {
		mUID = in.readString();
		mUsername = in.readString();
		mName = in.createStringArray();
		mAddress = in.readParcelable(Address.class.getClassLoader());
		mEmails = in.createStringArray();
		mMobile = in.readString();
		mGradYear = in.readInt();
		mPicture = in.readParcelable(Bitmap.class.getClassLoader());
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(mUID);
		dest.writeString(mUsername);
		dest.writeStringArray(mName);
		dest.writeParcelable(mAddress, flags);
		dest.writeStringArray(mEmails);
		dest.writeString(mMobile);
		dest.writeInt(mGradYear);
		dest.writeValue(mPicture);
	}

	public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
		@Override
		public User createFromParcel(Parcel in) {
			return new User(in);
		}

		@Override
		public User[] newArray(int size) {
			return new User[size];
		}
	};
} public class BlockHandler {
	private static final String TAG = "BlockHandler";
	private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);

	public static EighthBlock[] parse(InputStream in) throws JSONException, ParseException {
		return parse(Utils.inputStreamToJSON(in));
	}

	public static EighthBlock[] parse(JSONObject item) throws JSONException, ParseException {
		final JSONArray results = item.getJSONArray("results");
		final EighthBlock[] blocks = new EighthBlock[results.length()];
		JSONObject block;

		for (int i = 0; i < results.length(); i++) {
			block = results.getJSONObject(i);
			blocks[i] = new EighthBlock.Builder()
					.date(FORMAT.parse(block.getString("date")))
					.BID(block.getInt("id"))
					.type(block.getString("block_letter").charAt(0))
					.locked(block.getBoolean("locked"))
					.build();
		}

		return blocks;
	}
} public class NewsHandler {
	private static final String TAG = "NewsHandler";
	private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);

	public static NewsPost[] parse(InputStream in) throws JSONException, ParseException {
		return parse(Utils.inputStreamToJSON(in));
	}

	public static NewsPost[] parse(JSONObject item) throws JSONException, ParseException {
		final JSONArray results = item.getJSONArray("results");
		final NewsPost[] posts = new NewsPost[results.length()];
		JSONObject post;

		for (int i = 0; i < results.length(); i++) {
			post = results.getJSONObject(i);
			posts[i] = new NewsPost.Builder()
					.URL(post.getString("url"))
					.ID(post.getInt("id"))
					.title(post.getString("title"))
					.content(post.getString("content"))
					.author(post.getString("author"))
					.user(post.isNull("user") ? -1 : post.getInt("user"))
					.added(parseDate(post.getString("added")))
					.updated(parseDate(post.getString("updated")))
					.build();
		}
		return posts;
	}

	// Drop the milliseconds due to API producing different date formats
	private static Date parseDate(String date) throws ParseException {
		if (date == null) {
			return null;
		}
		if (date.indexOf('.') < 0) {
			return FORMAT.parse(date.substring(0, date.length() - 1));
		}
		return FORMAT.parse(date.substring(0, date.lastIndexOf('.')));
	}
} public class ScheduleHandler {
	private static final String TAG = "ScheduleHandler";
	private static final DateFormat mFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);

	public static Schedule[] parseAll(JSONObject schedule) throws JSONException, ParseException {
		final JSONArray scheduleArray = schedule.getJSONArray("results");
		final Schedule[] schedules = new Schedule[scheduleArray.length()];
		for (int index = 0; index < scheduleArray.length(); index++) {
			schedules[index] = parseSchedule(scheduleArray.getJSONObject(index));
		}
		Arrays.sort(schedules);
		return schedules;
	}

	public static Schedule parseSchedule(JSONObject schedule) throws JSONException, ParseException {
		final String[] items = getItems(schedule.getJSONObject("day_type").getJSONArray("blocks"));
		final Date date = mFormat.parse(schedule.getString("date"));
		return new Schedule.Builder()
				.date(date)
				.type(schedule.getJSONObject("day_type").getString("name"))
				.blocks(items[0])
				.times(items[1])
				.build();
	}

	private static String[] getItems(JSONArray blocks) throws JSONException {
		final String[] items = {"", ""};
		JSONObject block;
		for (int i = 0; i < blocks.length(); i++) {
			block = blocks.getJSONObject(i);
			items[0] += "\n" + block.getString("name");
			items[1] += "\n" + block.getString("start") + " - " + block.getString("end");
		}
		return items;
	}
} public class SelectedBlockHandler {
	private static final String TAG = "SelectedBlockHandler";

	public static EighthActivity[] parse(InputStream in) throws JSONException, ParseException {
		return parse(Utils.inputStreamToJSONArray(in));
	}

	public static EighthActivity[] parse(JSONArray items) throws JSONException, ParseException {
		final EighthActivity[] activities = new EighthActivity[items.length()];
		JSONObject item, block, activity;

		for (int i = 0; i < items.length(); i++) {
			item = items.getJSONObject(i);
			block = item.getJSONObject("block");
			activity = item.getJSONObject("activity");
			activities[i] = new EighthActivity.Builder()
					.BID(block.getInt("id"))
					.AID(activity.getInt("id"))
					.name(activity.getString("title"))
					.URL(activity.getString("url"))
					.build();
		}

		return activities;
	}
} public class UserHandler {
	private static final String TAG = "ProfileHandler";

	public static User parse(InputStream in) throws JSONException, ParseException {
		return parse(Utils.inputStreamToJSON(in));
	}

	public static User parse(JSONObject user) throws JSONException, ParseException {
//		final JSONObject address = user.getJSONObject("address");

		return new User.Builder()
				.UID(user.getString("id"))
				.username(user.getString("ion_username"))
				.firstName(user.getString("first_name"))
				.middleName(user.getString("middle_name"))
				.lastName(user.getString("last_name"))
//				.street(address.getString("street"))
//				.city(address.getString("city"))
//				.state(address.getString("state"))
//				.postalCode(address.getString("postal_code"))
				.emails(Utils.JSONArrayToStringArray(user.getJSONArray("emails")))
				.phone(user.getString("home_phone"))
				.mobile(user.getString("mobile_phone"))
				.gradYear(user.getInt("graduation_year"))
				.build();
	}
} public abstract class AbstractDrawerActivity extends RequestActivity implements
		NavigationView.OnNavigationItemSelectedListener {
	private DrawerLayout mDrawerLayout;
	private NavigationView mNavigationView;
	private ActionBarDrawerToggle mDrawerToggle;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_home);

		mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		mNavigationView = (NavigationView) mDrawerLayout.findViewById(R.id.navigation);
		mNavigationView.setNavigationItemSelectedListener(this);

		// Use material design toolbar
		final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
		if (toolbar != null) {
			setSupportActionBar(toolbar);
		}

		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
		getSupportActionBar().setHomeButtonEnabled(true);

		mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.action_drawer_close,
				R.string.action_drawer_close) {
			public void onDrawerClosed(View view) {
				invalidateOptionsMenu();
			}

			public void onDrawerOpened(View drawerView) {
				invalidateOptionsMenu();
			}
		};
		mDrawerLayout.setDrawerListener(mDrawerToggle);
	}

	@Override
	protected void onPostCreate(Bundle savedInstanceState) {
		super.onPostCreate(savedInstanceState);
		mDrawerToggle.syncState();
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		mDrawerToggle.onConfigurationChanged(newConfig);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		return mDrawerToggle.onOptionsItemSelected(item);
	}

	@Override
	public boolean onNavigationItemSelected(MenuItem item) {
		if (item.isCheckable()) {
			item.setChecked(true);
		}
		mDrawerLayout.closeDrawer(GravityCompat.START);
		return true;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_MENU) {
			if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
				mDrawerLayout.closeDrawer(GravityCompat.START);
			} else {
				mDrawerLayout.openDrawer(GravityCompat.START);
			}
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public void onBackPressed() {
		if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
			mDrawerLayout.closeDrawer(GravityCompat.START);
			return;
		}
		super.onBackPressed();
	}
} public class Utils {
	public static final String TAG = "Utils";
	public static final String PREFS_NAME = "LOGIN";

	public static class API {
		private static final String PREFIX = "https://ion.tjhsst.edu/api";
		private static final String POSTFIX = "?format=json";
		private static final String BLOCK = PREFIX + "/blocks";
		private static final String ACTIVITY = PREFIX + "/activities";

		public static final String LOGIN = PREFIX;
		public static final String PROFILE = PREFIX + "/profile" + POSTFIX;
		public static final String BLOCKS = BLOCK + POSTFIX;
		public static final String SCHEDULE = PREFIX + "/schedule" + POSTFIX;
		public static final String SIGNUP = PREFIX + "/signups/user" + POSTFIX;
		public static final String ACTIVITIES = ACTIVITY + POSTFIX;
		public static final String NEWS = PREFIX + "/announcements" + POSTFIX;

		public static String activity(int activity) {
			return ACTIVITY + "/" + activity + POSTFIX;
		}

		public static String block(int block) {
			return BLOCK + "/" + block + POSTFIX;
		}

		public static String schedule(int page, int size) {
			return SCHEDULE + "&page=" + page + "&page_size=" + size;
		}

		public static String profilePic(String uid) {
			return PREFIX + "/profile/" + uid + "/picture";
		}
	}

	public static JSONObject inputStreamToJSON(InputStream inputStream) {
		try {
			final String temp = inputStreamToBufferedString(inputStream);
			if (temp == null) {
				return null;
			}
			return new JSONObject(temp);
		} catch (JSONException e) {
			Log.e(TAG, "Exception", e);
		}
		return null;
	}

	public static JSONArray inputStreamToJSONArray(InputStream inputStream) {
		try {
			final String temp = inputStreamToBufferedString(inputStream);
			if (temp == null) {
				return null;
			}
			return new JSONArray(temp);
		} catch (JSONException e) {
			Log.e(TAG, "Exception", e);
		}
		return null;
	}

	private static String inputStreamToBufferedString(InputStream inputStream) {
		try {
			final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
			final StringBuilder sb = new StringBuilder();
			String line;
			while ((line = reader.readLine()) != null) {
				sb.append(line).append("\n");
			}
			reader.close();
			return sb.toString();
		} catch (IOException e) {
			Log.e(TAG, "Exception", e);
		} finally {
			try {
				if (inputStream != null) {
					inputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public static String inputStreamToString(InputStream inputStream) {
		final Scanner s = new java.util.Scanner(inputStream).useDelimiter("\\A");
		return s.hasNext() ? s.next() : null;
	}

	public static String[] JSONArrayToStringArray(JSONArray array) throws JSONException {
		final String[] generic = new String[array.length()];
		for (int i = 0; i < generic.length; i++) {
			generic[i] = array.getString(i);
		}
		return generic;
	}

	public static boolean[] JSONArrayToBooleanArray(JSONArray array) throws JSONException {
		final boolean[] generic = new boolean[array.length()];
		for (int i = 0; i < generic.length; i++) {
			generic[i] = array.getBoolean(i);
		}
		return generic;
	}

	public static String getAuthKey(SharedPreferences preferences) {
		final String username, password;
		if ((username = preferences.getString("username", null)) != null &&
				(password = preferences.getString("password", null)) != null) {
			return "Basic " + Base64.encodeToString((username + ":" + password).getBytes(), Base64.NO_WRAP);
		}
		return null;
	}

	public static <T> String join(T[] array) {
		return join(array, ", ");
	}

	public static <T> String join(T[] array, String delim) {
		final StringBuilder sb = new StringBuilder();
		for (T t : array) {
			if (sb.length() > 0) {
				sb.append(delim);
			}
			sb.append(t);
		}
		return sb.toString();
	}
}
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.el1t.iolite.R;
import com.el1t.iolite.model.EighthActivity;
import com.el1t.iolite.model.EighthBlock;
import com.el1t.iolite.model.NewsPost;
import com.el1t.iolite.model.Schedule;
import com.el1t.iolite.model.User;
import com.el1t.iolite.parser.BlockHandler;
import com.el1t.iolite.parser.NewsHandler;
import com.el1t.iolite.parser.ScheduleHandler;
import com.el1t.iolite.parser.SelectedBlockHandler;
import com.el1t.iolite.parser.UserHandler;
import com.el1t.iolite.util.AbstractDrawerActivity;
import com.el1t.iolite.util.Utils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import javax.net.ssl.HttpsURLConnection;
package com.el1t.iolite.ui;





/**
 * Created by El1t on 10/24/14.
 */

public class HomeActivity extends AbstractDrawerActivity implements BlockFragment.OnFragmentInteractionListener,
		ScheduleFragment.OnFragmentInteractionListener, NavigationView.OnNavigationItemSelectedListener,
		NewsFragment.OnFragmentInteractionListener {
	private static final String TAG = "Block Activity";
	private static final String ARG_USER = "user";
	private static final String ARG_FAKE = "fake";
	private static final String ARG_ACTIVE_VIEW = "active";
	private static final String ARG_FRAGMENT = "fragment";
	public static final int INITIAL_DAYS_TO_LOAD = 14;
	public static final int DAYS_TO_LOAD = 7;

	private BlockFragment mBlockFragment;
	private ScheduleFragment mScheduleFragment;
	private NewsFragment mNewsFragment;
	private User mUser;