@Singleton
public class DataProvider {

	public static int ITEMS_PER_PAGE = 40;

	@Inject
	private CondroidDatabase mDatabase;

	private Convention con;

	private List<Integer> favorited;

	private Map<Integer, ProgramLine> programLines = null;

	private List<Place> places;

	public boolean hasData() {
		return !mDatabase.isEmpty();
	}

	public List<Annotation> getAnnotations(SearchQueryBuilder con, int skip) {
		List<Annotation> ret = new ArrayList<Annotation>();
		String condition = null;
		if (con != null)
			condition = con.buildCondition();

		Cursor c = this.mDatabase.query(CondroidDatabase.ANNOTATION_TABLE, null, condition, null, "startTime ASC, lid ASC, title ASC", (skip) + "," + ITEMS_PER_PAGE);

		while (c.moveToNext()) {

			ret.add(readAnnotation(c));
		}
		c.close();
		return ret;
	}

	public ProgramLine getProgramLine(int lid) {
		if (programLines == null) {
			this.loadProgramLines();
		}
		if (programLines != null) {
			if (programLines.containsKey(lid)) {
				return programLines.get(lid);
			}
		}

		return new ProgramLine();
	}

	public Map<Integer, ProgramLine> getProgramLines() {
		if (programLines == null) {
			this.loadProgramLines();
		}
		return programLines;
	}

	private void loadProgramLines() {
		programLines = new HashMap<Integer, ProgramLine>();

		Cursor c = this.mDatabase.query(CondroidDatabase.LINE_TABLE, null, null, null, "title ASC", null);
		while (c.moveToNext()) {
			ProgramLine p = new ProgramLine();
			p.setLid(c.getInt(c.getColumnIndex("id")));
			p.setName(c.getString(c.getColumnIndex("title")));
			programLines.put(p.getLid(), p);
		}
		c.close();
	}

	public List<Date> getDates() {

		Cursor c = this.mDatabase.query("SELECT DISTINCT STRFTIME('%Y-%m-%d',startTime) AS sDate FROM " + CondroidDatabase.ANNOTATION_TABLE + " ORDER by STRFTIME('%Y-%m-%d',startTime) ASC");

		List<Date> map = new ArrayList<Date>();
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		if (c.getCount() > 0) {
			do {
				try {
					if (c.getString(c.getColumnIndex("sDate")) != null) {
						map.add(df.parse(c.getString(c.getColumnIndex("sDate"))));
					}
				} catch (ParseException e) {
					Log.e("Condroid", "Exception when parsing dates for list dialog.", e);
				}
			} while (c.moveToNext());

		}
		c.close();

		return map;
	}

	public List<Annotation> getRunningAndNext(SearchQueryBuilder sb, int skip) {
		List<Annotation> l = new ArrayList<Annotation>();
		String condition = "";
		if (sb != null) {
			condition = sb.buildCondition();
		}

		String now = DateTimeFactory.getNow().toDateTime(DateTimeZone.forID("UTC")).toString("yyyy-MM-dd HH:mm");
		if (skip == 0) {
			Cursor c = this.mDatabase.query(CondroidDatabase.ANNOTATION_TABLE, null, "startTime < '" + now + "' AND endTime > '" + now + "'" + (condition != null && !condition.equals("") ? " AND " + condition : ""), null, "startTime DESC, lid ASC, pid ASC", null, false);
			while (c.moveToNext()) {
				Annotation annotation = readAnnotation(c);

				l.add(annotation);

			}
			skip = c.getCount();
			c.close();
		}

		if (l.size() < ITEMS_PER_PAGE) {
			Cursor c2 = this.mDatabase.query(
					CondroidDatabase.ANNOTATION_TABLE,
					null,
					"(startTime < '" + now + "' AND endTime > '" + now + "') OR (startTime >'" + now + "')" + (condition != null && !condition.equals("") ? " AND " + condition : ""),
					null,
					"startTime ASC, lid ASC, pid ASC",
					(skip) + "," + (ITEMS_PER_PAGE - l.size()),
					false
			);
			Log.d("Condroid", "LIMIT: " + ((skip) + "," + (ITEMS_PER_PAGE - l.size())) + ", returned items " + c2.getCount());

			while (c2.moveToNext()) {
				Annotation annotation = readAnnotation(c2);
				l.add(annotation);
			}
			c2.close();
		}

		return l;
	}

	private Annotation readAnnotation(Cursor c) {
		Annotation annotation = new Annotation();
		annotation.setPid(c.getString(c.getColumnIndex("pid")));
		annotation.setTitle(c.getString(c.getColumnIndex("title")));
		annotation.setAnnotation(c.getString(c.getColumnIndex("annotation")));
		annotation.setAuthor(c.getString(c.getColumnIndex("talker")));
		annotation.setSQLEndTime(c.getString(c.getColumnIndex("endTime")));
		//annotation.setLength(c.getString(c.getColumnIndex("length")));
		annotation.setLocation(c.getString(c.getColumnIndex("location")));
		annotation.setImdb(c.getString(c.getColumnIndex("imdb")));
		annotation.setLid(c.getInt(c.getColumnIndex("lid")));
		annotation.setSQLStartTime(c.getString(c.getColumnIndex("startTime")));
		annotation.setType(c.getString(c.getColumnIndex("mainType")), c.getString(c.getColumnIndex("additionalTypes")));
		return annotation;
	}

	public Convention getCon() {
		if (this.con != null) {
			return con;
		}
		Cursor c = this.mDatabase.query(CondroidDatabase.CON_TABLE, null, null, null, null, null);
		Convention co = new Convention();
		while (c.moveToNext()) {
			co.setId(c.getInt(c.getColumnIndex("id")));
			co.setDate(c.getString(c.getColumnIndex("date")));
			co.setImage(c.getString(c.getColumnIndex("image")));
			co.setName(c.getString(c.getColumnIndex("name")));
			co.setUrl(c.getString(c.getColumnIndex("url")));
			co.setMessage(c.getString(c.getColumnIndex("message")));
			co.setGps(c.getString(c.getColumnIndex("gps")));
			DateTimeFormatter format = DateTimeFormat
					.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC();
			try {
				co.setLastUpdate(format.parseDateTime(c.getString(c.getColumnIndex("lastUpdate"))).toDate());
			} catch (Exception e) {
				Log.e("Condroid", "Parsing DB date", e);
				co.setLastUpdate(new Date());
			}
		}
		c.close();
		this.con = co;
		return co;
	}

	public List<Integer> getFavorited() {
		if (favorited != null) {
			return favorited;
		}
		Cursor c = this.mDatabase.query(CondroidDatabase.FAVORITE_TABLE, null, null, null, "pid ASC", null);
		favorited = new ArrayList<Integer>();

		while (c.moveToNext()) {
			favorited.add(c.getInt(c.getColumnIndex("pid")));
		}
		return favorited;
	}

	public boolean doFavorite(int pid) {
		Cursor c = this.mDatabase.query(CondroidDatabase.FAVORITE_TABLE, null, "pid=" + pid, null, null, null);
		favorited = null;
		if (c.getCount() > 0) {
			this.mDatabase.query("DELETE FROM " + CondroidDatabase.FAVORITE_TABLE + " WHERE pid = '" + pid + "'");
			return false;
		} else {
			this.mDatabase.query("INSERT INTO " + CondroidDatabase.FAVORITE_TABLE + " (pid) VALUES ('" + pid + "')");
			return true;
		}
	}

	public boolean setReminder(Annotation annotation, int i) {
		try {
			Cursor c = this.mDatabase.query("SELECT pid FROM " + CondroidDatabase.ANNOTATION_TABLE + " WHERE pid =" + annotation.getPid() + " AND startTime IS NOT NULL");
			if (c.getCount() > 0) {
				this.mDatabase.query("DELETE FROM " + CondroidDatabase.REMINDER_TABLE + " WHERE pid=" + annotation.getPid());
				this.mDatabase.query("INSERT INTO " + CondroidDatabase.REMINDER_TABLE + " (pid, minutes) VALUES ('" + annotation.getPid() + "','" + i + "')");
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public Integer getReminder(int pid) {
		Cursor c = this.mDatabase.query(CondroidDatabase.REMINDER_TABLE, null, "pid = " + pid, null, null, null);
		if (c.getCount() > 0) {
			c.moveToNext();
			return Integer.parseInt(c.getString(c.getColumnIndex("minutes")));
		} else {
			return null;
		}
	}

	public boolean removeReminder(int pid) {
		try {
			this.mDatabase.query("DELETE FROM " + CondroidDatabase.REMINDER_TABLE + " WHERE pid=" + pid);
			return true;
		} catch (Exception e) {
			Log.w("Condroid", e);
			return false;
		}
	}

	public Reminder getNextReminder() {
		Cursor c = this.mDatabase.query("SELECT r.minutes AS remind, a.pid, a.* FROM " + CondroidDatabase.REMINDER_TABLE + " r JOIN " + CondroidDatabase.ANNOTATION_TABLE + " a USING (pid) ORDER by startTime ASC LIMIT 1");
		if (c != null && c.getCount() > 0) {
			c.moveToFirst();
			Reminder r = new Reminder();
			r.annotation = this.readAnnotation(c);
			r.reminder = c.getInt(c.getColumnIndex("remind"));
			c.close();
			return r;
		}
		return null;
	}

	public List<Reminder> getReminderList() {
		List<Reminder> r = new ArrayList<Reminder>();

		Cursor c = this.mDatabase.query("SELECT r.minutes AS remind, a.pid, a.* FROM " + CondroidDatabase.REMINDER_TABLE + " r JOIN " + CondroidDatabase.ANNOTATION_TABLE + " a USING (pid) ORDER by startTime ASC LIMIT 20");
		if (c != null) {
			if (c.getCount() > 0)
				do {
					Reminder reminder = new Reminder();
					reminder.annotation = this.readAnnotation(c);
					reminder.reminder = c.getInt(c.getColumnIndex("remind"));
					r.add(reminder);
				} while (c.moveToNext());
			c.close();
		}
		return r;
	}

	public CondroidDatabase getDatabase() {
		return mDatabase;
	}

	public void clear() {
		this.programLines = null;
		this.con = null;
		this.favorited = null;
		this.places = null;
	}

	public List<Place> getPlaces() {
		if (this.places != null) {
			return this.places;
		}
		List<Place> ret = new ArrayList<Place>();

		Cursor c = this.mDatabase.query(CondroidDatabase.PLACES_TABLE, null, null, null, "category_sort ASC, sort ASC, name ASC", null);

		while (c.moveToNext()) {
			Place place = new Place();
			place.setId(c.getInt(c.getColumnIndex("id")));
			place.setName(c.getString(c.getColumnIndex("name")));
			place.setUrl(c.getString(c.getColumnIndex("url")));
			place.setCategory(c.getString(c.getColumnIndex("category")));
			place.setAddress(c.getString(c.getColumnIndex("address")));
			place.setCategorySort(c.getInt(c.getColumnIndex("category_sort")));
			place.setDescription(c.getString(c.getColumnIndex("description")));
			place.setHours(c.getString(c.getColumnIndex("hours")));
			place.setGps(c.getString(c.getColumnIndex("gps")));

			ret.add(place);
		}
		c.close();
		return this.places = ret;
	}

}
 public class SearchProvider {

	private static Map<String, SearchQueryBuilder> map;

	static {
		map = new HashMap<String, SearchQueryBuilder>();
	}

	public static SearchQueryBuilder getSearchQueryBuilder(String tag) {
		if (!map.containsKey(tag)) {
			map.put(tag, new SearchQueryBuilder());
		}
		return map.get(tag);
	}

	public static Map<String, SearchQueryBuilder> getSearchQueryBuilders() {
		return map;
	}

	public static void clear() {

		for (SearchQueryBuilder sb : map.values()) {
			sb.clear();
		}

		map = new HashMap<String, SearchQueryBuilder>();
	}
}
 public class SearchQueryBuilder {

	private Map<String, ICondition> params;

	public SearchQueryBuilder() {
		this.params = new HashMap<String, ICondition>();
	}

	public SearchQueryBuilder addParam(final String value) {
		if (value != null) {
			this.params.put(String.class.getName(), new ICondition() {
				@Override
				public String getCondition() {
					String norm = Annotation.normalize(value);
					return "pid LIKE '%" + value + "%' OR normalizedTitle LIKE '%" + norm + "%' OR LOWER(talker) LIKE '%" + norm + "%'";
				}

				@Override
				public String getReadable() {
					return "*" + value + "*";  //To change body of implemented methods use File | Settings | File Templates.
				}
			});
		}

		return this;
	}

	public SearchQueryBuilder addParam(ICondition value) {
		this.params.put(value.getClass().getName(), value);
		return this;
	}

	public SearchQueryBuilder addParam(ICondition value, String key) {
		this.params.put(key, value);
		return this;
	}

	public SearchQueryBuilder removeParam(Object value) {
		this.params.remove(value.getClass().getName());
		return this;
	}

	public boolean hasParam(String name) {
		return this.params.containsKey(name);

	}

	public void addParam(final Date d) {
		final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		this.addParam(new ICondition() {

			public String getCondition() {
				Date d2 = (Date) d.clone();
				d2.setDate(d.getDate() + 1);
				return "(startTime >=DATE('" + df.format(d) + "') AND startTime < DATE('" + df.format(d2) + "'))";
			}

			@Override
			public String getReadable() {
				return new SimpleDateFormat("dd.MM.yy").format(d);
			}
		}, Date.class.getName());
	}

	public String buildCondition() {
		String condition = "";
		for (String key : params.keySet()) {
			if (!condition.equals("")) {
				condition += " AND ";
			}
			String cd = params.get(key).getCondition();
			if (!cd.trim().equals("")) {
				condition += " (" + cd + ")";
			}
		}
		Log.d("Condroid", "Builded URL " + condition);
		return condition;
	}

	public void clear() {
		params.clear();
	}

	public boolean isEmpty() {
		return params.isEmpty();
	}

	public String getReadableCondition() {
		String ret = "Filtr: ";
		for (String key : params.keySet()) {
			if (!ret.equals("Filtr: ")) {
				ret += " & ";
			}
			ret += params.get(key).getReadable();
		}
		return ret;
	}
}
 public class Annotation implements Serializable, DBInsertable {

	private static final long serialVersionUID = 29890241539328629L;

	private int pid;

	private String author;

	private String imdb;

	private String title;

	private AnnotationType type = new AnnotationType();

	private String programLine;

	private String annotation = "";

	private Date start;

	private Date end;

	private String location;

	public static DateTimeFormatter dateISOFormatter = ISODateTimeFormat
			.dateTimeNoMillis();

	public static DateTimeFormatter dateSQLFormatter = DateTimeFormat
			.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC();

	private int lid;

	public Date getStart() {
		return start;
	}

	public Date getEnd() {
		return end;
	}

	public void setSQLStartTime(String startTime) {
		this.start = parseDate(startTime, dateSQLFormatter);
	}

	public void setSQLEndTime(String endTime) {
		this.end = parseDate(endTime, dateSQLFormatter);
	}

	private Date parseDate(String date, DateTimeFormatter formatter) {

		if (date == null || date.equals(""))
			return null;
		date = date.trim();
		Date x;
		if (date.length() < 25 && formatter.equals(dateISOFormatter)) {
			date = date.substring(0, date.length() - 6) + ":00" + date.substring(date.length() - 6);
		}
		x = formatter.parseDateTime(date).toDate();
		return x;

	}

	public int getPid() {
		return pid;
	}

	public String getAuthor() {
		return author;
	}

	public String getTitle() {
		return title;
	}

	public AnnotationType getType() {
		return this.type;
	}

	/**
	 * Use only during processing new XML!
	 */
	public String getProgramLine() {
		return programLine;
	}

	public String getAnnotation() {
		return annotation;
	}

	public void setPid(String pid) {
		try {
			this.pid = Integer.parseInt(pid.trim());
		} catch (NumberFormatException e) {
			//intentionally
		}
	}

	public void setAuthor(String talker) {
		if (talker != null) {
			this.author = talker.trim();
		}
	}

	public void setTitle(String title) {
		this.title = title.trim();
	}

	public void setType(AnnotationType type) {
		this.type = type;
	}

	public void setAnnotation(String annotation) {
		if (annotation != null) {
			this.annotation = annotation.trim();
		}
	}

	public ContentValues getContentValues() {

		if (start != null && end != null && start.after(end)) {
			end.setDate(end.getDate() + 1);
		}
		ContentValues ret = new ContentValues();
		ret.put("pid", this.pid);
		ret.put("talker", author);
		ret.put("title", title);
		ret.put("imdb", imdb);
		ret.put("mainType", this.type.mainType);
		ret.put("additionalTypes", TextUtils.join("+", this.type.secondaryTypes));
		ret.put("normalizedTitle", normalize(title));

		ret.put("lid", lid);

		ret.put("location", location);
		ret.put("annotation", annotation);
		if (start != null) {
			ret.put("startTime", dateSQLFormatter.print(start.getTime()));
		}
		if (end != null) {
			ret.put("endTime", dateSQLFormatter.print(end.getTime()));
		}

		return ret;
	}

	public void setLid(Integer integer) {
		lid = integer;

	}

	public int getLid() {
		return lid;
	}

	public void setLocation(String nextText) {
		location = nextText;
	}

	public String getLocation() {
		return location;
	}

	public String[] getAdditionalTypes() {
		return (String[]) type.secondaryTypes.toArray();
	}

	private static final HashMap<Character, Character> accents = new HashMap<Character, Character>() {
		{
			put('ě', 'e');
			put('š', 's');
			put('č', 'c');
			put('ř', 'r');
			put('ž', 'z');
			put('ý', 'y');
			put('á', 'a');
			put('í', 'i');
			put('é', 'e');

			put('ú', 'u');
			put('ů', 'u');
			put('ľ', 'l');
			put('ŕ', 'r');
			put('ť', 't');
			put('ü', 'u');
			put('ä', 'a');
			put('ï', 'i');
			put('ë', 'e');
			put('ó', 'o');
			put('ś', 's');
			put('ď', 'd');
			put('ĺ', 'l');
			put('ź', 'z');
			put('ć', 'c');
			put('ň', 'n');
		}
	};

	public static String normalize(String title) {
		char[] normalized = title.toLowerCase().toCharArray();
		for (int i = 0; i < normalized.length; i++) {
			Character x = accents.get(normalized[i]);
			if (x != null)
				normalized[i] = x;
		}
		return new String(normalized);
	}

	public void setType(String mainType, String additionalTypes) {
		this.type = new AnnotationType();
		this.type.mainType = mainType;
		this.type.secondaryTypes = Arrays.asList(additionalTypes.split("\\+"));
	}

	public void setImdb(String imdb) {
		this.imdb = imdb;
	}

	public String getImdb() {
		return imdb;
	}
}
 public class ShowAnnotation extends RoboSherlockActivity {

	private Annotation annotation;

	private static DateFormat hourFormat = new SimpleDateFormat("HH:mm");

	private static DateFormat dayFormat = new SimpleDateFormat(
			"EE dd.MM.", new Locale("cs", "CZ"));

	@Inject
	private DataProvider provider;

	private Thread updateThread;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.annotation = (Annotation) this.getIntent().getSerializableExtra(
				"annotation");

		this.setContentView(R.layout.annotation);

		getSupportActionBar().setDisplayHomeAsUpEnabled(true);

		this.setupIcons();
		this.addTypes();

		TextView title = (TextView) this.findViewById(R.id.annot_title);
		title.setText(this.annotation.getTitle());

		if (this.annotation.getAuthor() != null && !this.annotation.getAuthor().trim().equals("")) {
			TextView author = (TextView) this.findViewById(R.id.annot_author);
			author.setText(this.annotation.getAuthor());
		} else {
			this.findViewById(R.id.iAuthor).setVisibility(View.GONE);
			this.findViewById(R.id.annot_author).setVisibility(View.GONE);
		}
		TextView pid = (TextView) this.findViewById(R.id.annot_pid);
		pid.setText("#" + this.annotation.getPid());

		TextView line = (TextView) this.findViewById(R.id.tLine);
		line.setText(this.provider.getProgramLine(this.annotation.getLid()).getName());
		if (this.annotation.getLocation() != null && !this.annotation.getLocation().trim().equals("")) {
			TextView location = (TextView) this.findViewById(R.id.annot_location);
			location.setText(this.annotation.getLocation());
		} else {
			findViewById(R.id.lLocation).setVisibility(View.GONE);
		}

		TextView text = (TextView) this.findViewById(R.id.annot_text);
		text.setText(this.annotation.getAnnotation());

		if (this.annotation.getImdb() != null && !this.annotation.getImdb().trim().equals("")) {
			ImageView i = (ImageView) findViewById(R.id.iImdb);
			i.setVisibility(View.VISIBLE);
			i.setOnClickListener(new ImdbClickListener(this, this.annotation));
		} else {
			findViewById(R.id.iImdb).setVisibility(View.GONE);
		}

	}

	@Override
	protected void onResume() {
		super.onResume();
		this.setupDates();
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (updateThread != null) {
			updateThread.interrupt();
			updateThread = null;
		}
	}

	private void setupDates() {

		if (annotation.getStart() != null && annotation.getEnd() != null) {
			findViewById(R.id.lTimeLayout).setVisibility(View.VISIBLE);

			TextView tStart = (TextView) findViewById(R.id.tStart);
			TextView tEnd = (TextView) findViewById(R.id.tEnd);

			tStart.setText(hourFormat.format(annotation.getStart()));
			tEnd.setText(hourFormat.format(annotation.getEnd()));

			if (!this.isDateToday(annotation.getStart())) {
				TextView day = (TextView) findViewById(R.id.tDay);
				day.setText(dayFormat.format(annotation.getStart()));
				day.setVisibility(View.VISIBLE);
			} else {
				findViewById(R.id.tDay).setVisibility(View.GONE);
			}

			if (isRunning()) {
				findViewById(R.id.lRunningNow).setVisibility(View.VISIBLE);
				findViewById(R.id.lStartsInMinutes).setVisibility(View.GONE);
			} else if (isStartingShortly(60)) {
				findViewById(R.id.lRunningNow).setVisibility(View.GONE);
				findViewById(R.id.lStartsInMinutes).setVisibility(View.VISIBLE);

				TextView info = (TextView) findViewById(R.id.tStartsShortly);

				Calendar c = Calendar.getInstance();
				c.setTime(annotation.getStart());

				int minutes = this.getMinutesToStart();

				String text = getString(R.string.startsInXMinutes);
				if (minutes < 1) {
					text += " " + getString(R.string.lessThanMinute);
				} else {
					text += " " + this.getResources().getQuantityString(R.plurals.minutes, minutes, minutes);
				}

				info.setText(text);
			} else {
				findViewById(R.id.lRunningNow).setVisibility(View.GONE);
				findViewById(R.id.lStartsInMinutes).setVisibility(View.GONE);
			}
			if (new Date().after(annotation.getEnd())) {
				findViewById(R.id.lMisssed).setVisibility(View.VISIBLE);
			} else {
				findViewById(R.id.lMisssed).setVisibility(View.GONE);
			}

			if (isRunning() || isStartingShortly(60)) {
				if (updateThread == null) {
					Log.d(this.getClass().getName(), "Starting thread.");
					updateThread = new Thread() {
						@Override
						public void run() {
							try {
								while (!isInterrupted()) {
									Thread.sleep(30 * 1000);

									runOnUiThread(new Runnable() {
										@Override
										public void run() {
											Log.d(this.getClass().getName(), "Updating");
											ShowAnnotation.this.setupDates();
										}
									});
								}
							} catch (InterruptedException ignored) {

							}
							Log.d(this.getClass().getName(), "Thread interrupted");
						}
					};
					updateThread.start();
				}

			}

		} else {
			findViewById(R.id.lTimeLayout).setVisibility(View.GONE);

			findViewById(R.id.lRunningNow).setVisibility(View.GONE);
			findViewById(R.id.lStartsInMinutes).setVisibility(View.GONE);
			findViewById(R.id.lMisssed).setVisibility(View.GONE);
		}

	}

	private boolean isStartingShortly(int minutes) {

		int toStart = getMinutesToStart();

		return toStart < minutes && toStart >= 0;
	}

	private int getMinutesToStart() {
		Duration duration = new Duration(new Instant().getMillis(), annotation.getStart().getTime());

		return (int) duration.getStandardMinutes();
	}

	private boolean isRunning() {
		Date now = new Date();

		return this.annotation.getStart().before(now) && this.annotation.getEnd().after(now);
	}

	private void setupIcons() {
		Typeface type = Typeface.createFromAsset(getAssets(), "fonts/fontawesome-webfont.ttf");

		TextView iAuthor = (TextView) findViewById(R.id.iAuthor);
		TextView iLine = (TextView) findViewById(R.id.iLine);
		TextView iLocation = (TextView) findViewById(R.id.iLocation);

		iAuthor.setText(R.string.fa_user);
		iLine.setText(R.string.fa_bars);
		iLocation.setText(R.string.fa_map_marker);

		iAuthor.setTypeface(type);
		iLine.setTypeface(type);
		iLocation.setTypeface(type);

	}

	private void addTypes() {
		TextView typeField = (TextView) this.findViewById(R.id.annot_type);
		ViewGroup parent = (ViewGroup) typeField.getParent();
		try {
			typeField.setText(this.getString(AnnotationType.getTextualType(annotation.getType().mainType)));
		} catch (IllegalStateException e) {
			typeField.setVisibility(View.GONE);
		}

		String[] aT = annotation.getAdditionalTypes();

		if (aT.length > 0) {
			for (String anAT : aT) {
				if (anAT.length() > 0) {
					TextView newField = new TextView(this.getApplicationContext());
					try {
						newField.setText(this.getString(AnnotationType.getTextualType(anAT)));
					} catch (IllegalStateException e) {
						continue;
					}

					newField.setBackgroundResource(R.color.condroidGreen);
					newField.setTextColor(getResources().getColor(R.color.white));
					newField.setPadding(typeField.getPaddingLeft(), typeField.getPaddingTop(), typeField.getPaddingRight(), typeField.getPaddingBottom());
					newField.setLayoutParams(typeField.getLayoutParams());

					parent.addView(newField);
				}
			}
		}
	}

	public Annotation getAnnotation() {
		return annotation;
	}

	boolean isDateToday(Date date) {
		Calendar today = Calendar.getInstance(TimeZone.getDefault(), new Locale("cs", "CZ"));
		today.setTime(new Date());

		Calendar compared = Calendar.getInstance();
		compared.setTime(date);

		//its today
		return compared.get(Calendar.YEAR) == today.get(Calendar.YEAR)
				&& compared.get(Calendar.MONTH) == today.get(Calendar.MONTH)
				&& compared.get(Calendar.DAY_OF_MONTH) == today.get(Calendar.DAY_OF_MONTH);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater mi = this.getSupportMenuInflater();
		mi.inflate(R.menu.show_annotation, menu);
		ShareActionProvider mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.mShare).getActionProvider();
		if (mShareActionProvider == null) {
			menu.findItem(R.id.mShare).setVisible(false);
		} else {
			mShareActionProvider.setShareIntent(new ShareProgramListener(this).getShareActionIntent(this.annotation));
		}

		if (provider.getFavorited().contains(Integer.valueOf(annotation.getPid()))) {
			menu.findItem(R.id.mFavorite).setIcon(R.drawable.star_yellow);
		}

		super.onCreateOptionsMenu(menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case android.R.id.home:
				Intent intent = new Intent(this, MainActivity.class);
				intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
				startActivity(intent);
				return true;
			case R.id.mReminder:
				new SetReminderListener(this, provider).invoke(this.annotation);
				return true;
			case R.id.mFavorite:
				if (new MakeFavoritedListener(this).invoke(this.annotation)) {
					item.setIcon(R.drawable.star_yellow);
				} else {
					item.setIcon(R.drawable.star_white);
				}
				return true;
			default:
				break;
		}
		return super.onOptionsItemSelected(item);
	}

}
 public class EndlessAdapter extends com.commonsware.cwac.endless.EndlessAdapter {

	private IAdapterDataProvider dataLoader;

	private RotateAnimation rotate;

	protected List<Annotation> itemsToAdd;

	// protected int totalItems = 0;
	private Activity activity;

	public EndlessAdapter(Activity activity, BaseAdapter wrapped, IAdapterDataProvider<Annotation> dataLoader) {
		super(wrapped);

		this.activity = activity;
		rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF,
				0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		rotate.setDuration(1000);
		rotate.setRepeatMode(Animation.RESTART);
		rotate.setRepeatCount(Animation.INFINITE);
		if (wrapped.getCount() < DataProvider.ITEMS_PER_PAGE) {
			this.stopAppending();
		}
		this.dataLoader = dataLoader;
		wrapped.registerDataSetObserver(new DataSetObserver() {
			@Override
			public void onChanged() {
				EndlessAdapter.this.notifyDataSetChanged();
			}

			@Override
			public void onInvalidated() {
				EndlessAdapter.this.notifyDataSetInvalidated();
			}
		});
	}

	public void setItems(List<Annotation> items) {
		IReplaceable a = (IReplaceable) this.getWrappedAdapter();

		a.replace(items);

		if (items.size() < DataProvider.ITEMS_PER_PAGE) {
			this.stopAppending();
		} else {
			this.restartAppending();
		}

	}

	@Override
	protected boolean cacheInBackground() throws Exception {
		if (this.getCount() == 0) {
			return false;
		}
		ListAdapter wrappedAdapter = this.getWrappedAdapter();
		int count = wrappedAdapter.getCount();
		if (wrappedAdapter instanceof GroupedAdapter) {
			count = ((GroupedAdapter) wrappedAdapter).getEntriesCount();
		}
		this.itemsToAdd = this.getPrecachedData(count);

		return !(itemsToAdd.size() < DataProvider.ITEMS_PER_PAGE);
	}

	private List<Annotation> getPrecachedData(int skip) {
		return this.dataLoader.getData(skip);
	}

	@Override
	protected void appendCachedData() {
		if (this.itemsToAdd != null && this.itemsToAdd.size() > 0) {
			IAppendable a = (IAppendable) this.getWrappedAdapter();

			a.append(this.itemsToAdd);

			this.itemsToAdd = null;
		}

	}

	@Override
	protected View getPendingView(ViewGroup parent) {
		View row = activity.getLayoutInflater().inflate(R.layout.row, null);

		View child = row.findViewById(R.id.throbber);
		row.setClickable(false);
		row.setFocusable(false);
		child.startAnimation(rotate);

		return (row);
	}

}
 public class GroupedAdapter extends BaseAdapter implements IAppendable, IReplaceable {

	private final Context context;

	List<Entry> entries;

	@Inject
	ViewHelper viewHelper;

	public GroupedAdapter(Context context, List<Annotation> items) {
		this.context = context;
		RoboGuice.getInjector(context).injectMembers(this);
		this.entries = new ArrayList<Entry>();

		this.addAnnotations(items);
	}

	private void addAnnotations(List<Annotation> items) {
		if (items.size() == 0) {
			return;
		}

		Collections.sort(items, new Comparator<Annotation>() {
			@Override
			public int compare(Annotation lhs, Annotation rhs) {
				return lhs.getStart().compareTo(rhs.getStart());
			}
		});
		Date previous = null;
		if (!this.entries.isEmpty()) {
			for (int i = this.entries.size() - 1; i > 0; i--) {
				Entry item = this.entries.get(i);
				if (!item.isSeparator()) {
					previous = item.annotation.getStart();
					break;
				}
			}
		}
		if (previous == null) {
			previous = items.get(0).getStart();
			this.entries.add(new Entry(previous));
		}
		boolean nowHeader = DateHelper.isBeforeNow(previous);

		for (Annotation annotation : items) {
			if (!annotation.getStart().equals(previous)) {
				if (!DateHelper.isBeforeNow(annotation.getStart()) || !nowHeader) {
					this.entries.add(new Entry(annotation.getStart()));
					if (DateHelper.isBeforeNow(previous)) {
						nowHeader = true;
					}
				}
			}
			this.entries.add(new Entry(annotation));
			previous = annotation.getStart();
		}

	}

	@Override
	public int getCount() {
		return this.entries.size();
	}

	public int getEntriesCount() {
		int count = 0;
		for (Entry e : this.entries) {
			if (e.isSeparator()) {
				continue;
			}
			count++;
		}
		return count;
	}

	@Override
	public Entry getItem(int position) {
		return this.entries.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (convertView == null) {
			LayoutInflater inflater = ((Activity) this.context).getLayoutInflater();
			convertView = inflater.inflate(R.layout.annotation_list_item, parent, false);

			if (convertView == null) {
				return null;
			}
			viewHelper.setFavoritedIcon(this.context.getAssets(), convertView);
			ViewHolder holder = new ViewHolder();
			this.viewHelper.initializeItemLayout(convertView, holder);
			holder.runningTitle = (TextView) convertView.findViewById(R.id.tRunningTitle);
			convertView.setTag(R.id.listItem, holder);
		}

		Entry entry;
		try {
			entry = this.getItem(position);
		} catch (IndexOutOfBoundsException e) {
			return null;
		}
		if (entry != null) {
			this.setLayout(convertView, entry);
			if (entry.isSeparator()) {
				ViewHolder holder = (ViewHolder) this.viewHelper.getViewHolder(convertView);
				return this.inflanteSeparator(convertView, entry.header, holder);
			} else {
				return this.viewHelper.inflateAnnotation(convertView, entry.annotation);
			}
		}

		return null;
	}

	private void setLayout(View v, Entry item) {
		LayoutHolder lh = (LayoutHolder) v.getTag(R.id.layoutList);
		if (lh == null) {
			lh = new LayoutHolder();
			lh.separatorLayout = v.findViewById(R.id.ldateLayout);
			lh.itemLayout = v.findViewById(R.id.lItemLayout);
			v.setTag(R.id.layoutList, lh);
		}
		if (item.isSeparator()) {
			lh.separatorLayout.setVisibility(View.VISIBLE);
			lh.itemLayout.setVisibility(View.GONE);
		} else {
			lh.itemLayout.setVisibility(View.VISIBLE);
			lh.separatorLayout.setVisibility(View.GONE);
		}
	}

	private View inflanteSeparator(View view, Date header, ViewHolder holder) {
		if (header.before(DateTimeFactory.getNow().toDate())) {
			holder.runningTitle.setText(R.string.runningNow);
		} else {
			if (this.viewHelper.isDateToday(header)) {
				holder.runningTitle.setText(this.context.getString(R.string.today) + ", " + ViewHelper.todayFormat.format(header));
			} else {
				holder.runningTitle.setText(ViewHelper.dayFormat.format(header));
			}
		}
		view.setFocusable(false);
		view.setClickable(false);
		return view;
	}

	@Override
	public void append(List<Annotation> items) {
		this.addAnnotations(items);
		this.notifyDataSetChanged();
	}

	@Override
	public void replace(List<Annotation> items) {
		this.entries = new ArrayList<Entry>();
		this.addAnnotations(items);
		this.notifyDataSetChanged();
	}

	public Annotation getTopItem() {
		Annotation earliest = null;
		for (Entry e : this.entries) {
			if (e.isSeparator()) {
				continue;
			}
			if (earliest == null || earliest.getEnd().after(e.annotation.getEnd())) {
				earliest = e.annotation;
			}
		}
		return earliest;
	}

	public static class Entry {

		public Annotation annotation;

		public Date header;

		public Entry(Annotation a) {
			this.annotation = a;
		}

		public Entry(Date a) {
			this.header = a;
		}

		public boolean isSeparator() {
			return annotation == null;
		}

	}

	class ViewHolder extends ViewHelper.ViewHolder {

		TextView runningTitle;
	}

	class LayoutHolder {

		View separatorLayout;

		View itemLayout;
	}
}
 public class DisableFilterListener implements View.OnClickListener {

	private NewCondroidFragment parent;

	public DisableFilterListener(NewCondroidFragment activity) {
		this.parent = activity;
	}

	@Override
	public void onClick(View view) {
		String[] data = parent.getResources().getStringArray(R.array.disableFilterBy);

		Map<Integer, Object> selected = new HashMap<Integer, Object>();
		List<String> values = new ArrayList<String>();

		SearchQueryBuilder sb = SearchProvider.getSearchQueryBuilder(parent.getClass().getName());

		if (sb.hasParam(String.class.getName())) {
			values.add(data[0]);
			selected.put(values.size() - 1, "");
		}
		if (sb.hasParam(Date.class.getName())) {
			values.add(data[1]);
			selected.put(values.size() - 1, new Date());
		}
		if (sb.hasParam(ProgramLine.class.getName())) {
			values.add(data[2]);
			selected.put(values.size() - 1, new ProgramLine());
		}
		if (sb.hasParam(Object.class.getName())) {
			values.add(data[3]);
			selected.put(values.size() - 1, new Object());
		}
		values.add(data[4]);
		selected.put(values.size() - 1, -1);
		DisableFilterTypeSelected listener = new DisableFilterTypeSelected(parent, sb, selected);

		if (selected.size() <= 2) {
			listener.onClick(null, -1);
			return;
		}
		AlertDialog.Builder ab = new AlertDialog.Builder(parent.getActivity());
		ab.setTitle(R.string.disableFilter);

		ab.setItems(values.toArray(new String[selected.size()]), listener);

		ab.create().show();
	}
}
 public class MakeFavoritedListener {

	@Inject
	private DataProvider provider;

	public MakeFavoritedListener(Context context) {
		RoboGuice.getInjector(context).injectMembers(this);
	}

	public boolean invoke(Annotation annotation) {
		return this.invoke(annotation.getPid());
	}

	public boolean invoke(int pid) {
		return provider.doFavorite(pid);
	}

} public class SetReminderListener implements OnClickListener {

	Activity activity;

	int[] minutes = {0, 2, 5, 10, 15, 20, 30};

	private DataProvider provider;

	public SetReminderListener(Activity activity, DataProvider provider) {
		super();
		this.activity = activity;
		this.provider = provider;
	}

	public void onClick(View v) {
		this.invoke(((ShowAnnotation) activity).getAnnotation());
	}

	public void invoke(final Annotation annotation) {
		if (annotation.getStart() == null) {
			Toast.makeText(activity, "Program nemá zadaný čas - nelze nastavit připomenutí!", Toast.LENGTH_LONG).show();
			return;
		}
		AlertDialog.Builder ab = new AlertDialog.Builder(activity);
		ab.setTitle(R.string.remind);
		Integer exReminder = provider.getReminder(annotation.getPid());
		int selected = -1;
		if (exReminder != null) {
			for (int i = 0; i < minutes.length; i++) {
				if (exReminder == minutes[i]) {
					selected = i;
					break;
				}
			}
		}
		ab.setSingleChoiceItems(R.array.remindBefore, selected, new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
				if (provider.setReminder(annotation, minutes[which])) {
					ReminderManager.updateAlarmManager(activity);
					Toast.makeText(activity, "Upozornění bylo nastaveno.", Toast.LENGTH_SHORT).show();
				} else {
					Toast.makeText(activity, "Chyba - Nelze nastavit upozornění!", Toast.LENGTH_SHORT).show();
				}
			}
		});
		ab.create().show();
	}

}
 public class ShareProgramListener implements View.OnClickListener {

	Activity activity;

	public ShareProgramListener(Activity activity) {
		super();
		this.activity = activity;
	}

	public void onClick(View v) {
		this.invoke(((ShowAnnotation) activity).getAnnotation());
	}

	public void invoke(Annotation annotation) {
		activity.startActivity(Intent.createChooser(this.getShareActionIntent(annotation), "Sdílet"));
	}

	public Intent getShareActionIntent(Annotation annotation) {
		DateFormat dayFormat = new SimpleDateFormat(
				"EE dd.MM. HH:mm", new Locale("cs", "CZ"));
		DateFormat hourFormat = new SimpleDateFormat(
				"HH:mm", new Locale("cs", "CZ"));

		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("text/plain");
		intent.putExtra(Intent.EXTRA_TEXT, annotation.getTitle() +
						((annotation.getLocation() != null && !annotation.getLocation().equals("")) ? ", @" + annotation.getLocation() : "") +
						((annotation.getStart() != null && annotation.getEnd() != null) ? ", " + dayFormat.format(annotation.getStart()) + " - " + hourFormat.format(annotation.getEnd()) : "")
		);
		//intent.putExtra(Intent.EXTRA_SUBJECT, "Právě jsem na pořadu ");
		return intent;
	}

}

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import com.actionbarsherlock.view.Menu;
import com.github.rtyley.android.sherlock.roboguice.fragment.RoboSherlockFragment;
import com.google.inject.Inject;
import java.util.List;
import cz.quinix.condroid.R;
import cz.quinix.condroid.database.DataProvider;
import cz.quinix.condroid.database.SearchProvider;
import cz.quinix.condroid.database.SearchQueryBuilder;
import cz.quinix.condroid.model.Annotation;
import cz.quinix.condroid.ui.activities.ShowAnnotation;
import cz.quinix.condroid.ui.adapters.EndlessAdapter;
import cz.quinix.condroid.ui.adapters.GroupedAdapter;
import cz.quinix.condroid.ui.listeners.DisableFilterListener;
import cz.quinix.condroid.ui.listeners.MakeFavoritedListener;
import cz.quinix.condroid.ui.listeners.SetReminderListener;
import cz.quinix.condroid.ui.listeners.ShareProgramListener;
import roboguice.inject.InjectView;

package cz.quinix.condroid.ui.fragments;





public abstract class NewCondroidFragment extends RoboSherlockFragment implements AdapterView.OnItemClickListener {

	@Inject
	protected DataProvider dataProvider;

	@InjectView(R.id.lwMain)
	private ListView lwMain;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return inflater.inflate(R.layout.main_fragment, container, false);
	}

	@Override
	public void onStart() {
		super.onStart();
		initListView();
		this.updateSearchField();

	}

	@Override
	public void onResume() {
		super.onResume();
		if (this.lwMain != null && this.lwMain.getAdapter() != null) {
			((EndlessAdapter) this.lwMain.getAdapter()).notifyDataSetChanged();
		}
	}

	protected void initListView() {
		if (this.lwMain.getAdapter() == null) {
			//init
			this.lwMain.setAdapter(this.createListViewAdapter());
			this.lwMain.setOnItemClickListener(this);
			if (lwMain.getAdapter().getCount() == 0) {
				lwMain.setVisibility(View.GONE);
				this.getView().findViewById(R.id.tNoData).setVisibility(View.VISIBLE);
			}
			this.registerForContextMenu(lwMain);
		} else {
			((EndlessAdapter) lwMain.getAdapter()).notifyDataSetChanged();
		}

		this.updateSearchField();
	}

	protected abstract EndlessAdapter createListViewAdapter();

	protected EndlessAdapter getListViewAdapter() {
		return (EndlessAdapter) lwMain.getAdapter();
	}

	public boolean onContextItemSelected(android.view.MenuItem item) {

		if (!getUserVisibleHint()) {
			return false;
		}
		AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

		int menuItemIndex = item.getItemId();
		Object object = this.lwMain.getItemAtPosition(info.position);
		Annotation selected;
		if (object instanceof GroupedAdapter.Entry && !((GroupedAdapter.Entry) object).isSeparator()) {
			selected = ((GroupedAdapter.Entry) object).annotation;
		} else {
			selected = (Annotation) object;
		}

		switch (menuItemIndex) {
			case 0:

				new ShareProgramListener(this.getActivity()).invoke(selected);
