public class ZabbixLoginRequiredException extends Exception {

	private static final long serialVersionUID = 537466652124519153L;

	public ZabbixLoginRequiredException() {

	}

	public ZabbixLoginRequiredException(Throwable t) {
		super(t);
	}
} @DatabaseTable(tableName = "application_item_relation")
public class ApplicationItemRelation {

	@DatabaseField(generatedId = true)
	private long id;
	public static final String COLUMN_APPLICATIONID = "applicationid";
	@DatabaseField(uniqueIndexName = "app_item_idx", foreign = true, columnName = COLUMN_APPLICATIONID)
	private Application application;
	public static final String COLUMN_HOSTID = "hostid";
	@DatabaseField(foreign = true, columnName = COLUMN_HOSTID)
	private Host host;
	public static final String COLUMN_ITEMID = "itemid";
	@DatabaseField(uniqueIndexName = "app_item_idx", foreign = true, foreignAutoRefresh = true, columnName = COLUMN_ITEMID)
	private Item item;

	// @DatabaseField
	// private long hostId;

	public ApplicationItemRelation() {

	}

	public ApplicationItemRelation(Application app, Host host, Item item) {
		this.application = app;
		this.host = host;
		this.item = item;
	}

	public long getId() {
		return id;
	}

	public Application getApplication() {
		return application;
	}

	public Item getItem() {
		return item;
	}

	public Host getHost() {
		return host;
	}

	public void setHost(Host host) {
		this.host = host;
	}

	public void setId(long id) {
		this.id = id;
	}

	public void setApplication(Application application) {
		this.application = application;
	}

	public void setItem(Item item) {
		this.item = item;
	}

} @DatabaseTable(tableName = "events")
public class Event implements Comparable<Event>, Sharable {

	public static final int VALUE_OK = 0;

	public static final String COLUMN_ID = "eventid";
	@DatabaseField(id = true, columnName = COLUMN_ID)
	long id;

	public static final String COLUMN_OBJECT_ID = "objectid";
	@DatabaseField(columnName = COLUMN_OBJECT_ID)
	long objectId;

	public static final String COLUMN_TRIGGER = "triggerid";
	@DatabaseField(columnName = COLUMN_TRIGGER, canBeNull = true, foreign = true, foreignAutoCreate = true, foreignAutoRefresh = true)
	Trigger trigger;

	// Caution: This is the timestamp in milliseconds!
	public static final String COLUMN_CLOCK = "clock";
	@DatabaseField(columnName = COLUMN_CLOCK)
	long clock;

	public static final String COLUMN_VALUE = "value";
	@DatabaseField(columnName = COLUMN_VALUE)
	int value;

	public static final String COLUMN_ACK = "acknowledged";
	@DatabaseField(columnName = COLUMN_ACK)
	boolean acknowledged;

	// only local
	@DatabaseField
	String hostNames;

	public Event() {
	}

	public Event(long id, long objectId, long clock, int value,
			boolean acknowledged) {
		this.id = id;
		this.objectId = objectId;
		this.clock = clock;
		this.value = value;
		this.acknowledged = acknowledged;
	}

	public String getDetailedString() {
		StringBuilder sb = new StringBuilder();
		sb.append("id=").append(id);
		sb.append(", ").append("source=").append(objectId);
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(clock);
		DateFormat dateFormatter = SimpleDateFormat.getDateTimeInstance(
				SimpleDateFormat.DEFAULT, SimpleDateFormat.DEFAULT);
		sb.append(", ").append("date=")
				.append(dateFormatter.format(cal.getTime()));
		sb.append(", ").append("value=").append(value);
		sb.append(", ").append("acknowledged=").append(acknowledged);
		sb.append(", ").append("trigger={").append(trigger).append("}");
		return sb.toString();
	}

	public long getId() {
		return id;
	}

	public long getObjectId() {
		return objectId;
	}

	public Trigger getTrigger() {
		return trigger;
	}

	public void setTrigger(Trigger t) {
		trigger = t;
	}

	public String getHostNames() {
		return hostNames;
	}

	public void setHostNames(String hostNames) {
		this.hostNames = hostNames;
	}

	public long getClock() {
		return clock;
	}

	public int getValue() {
		return value;
	}

	public void setId(long id) {
		this.id = id;
	}

	public void setObjectId(long objectId) {
		this.objectId = objectId;
	}

	public void setClock(long clock) {
		this.clock = clock;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public void setAcknowledged(boolean acknowledged) {
		this.acknowledged = acknowledged;
	}

	public boolean isAcknowledged() {
		return acknowledged;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("id=").append(id);
		sb.append(", ").append("objectId=").append(objectId);
		sb.append(", ").append("clock=").append(clock);
		sb.append(", ").append("value=").append(value);
		sb.append(", ").append("acknowledged=").append(acknowledged);
		sb.append(", ").append("hostNames=").append(hostNames);
		if (trigger != null)
			sb.append(", ").append("trigger={").append(trigger.toString())
					.append("}");
		return sb.toString();
	}

	@Override
	public int compareTo(Event another) {
		if (id == another.getId())
			return 0;
		if (clock < another.getClock())
			return 1;
		if (clock > another.getClock())
			return -1;
		if (trigger == null)
			return 1;
		if (another.getTrigger() == null)
			return -1;
		if (trigger.getId() > another.getTrigger().getId())
			return 1;
		else
			return -1;
	}

	@Override
	public String getSharableString(Context context) {
		if(context != null){
			Resources res = context.getResources();
			StringBuilder sb = new StringBuilder();
			sb.append(res.getString(R.string.event) + ":\n");
			Calendar cal = Calendar.getInstance();
			cal.setTimeInMillis(clock);
			DateFormat dateFormatter = SimpleDateFormat.getDateTimeInstance(
					SimpleDateFormat.SHORT, SimpleDateFormat.SHORT,
					Locale.getDefault());
			sb.append("\t" + res.getString(R.string.time) + ": "
					+ dateFormatter.format(clock) + "\n");
			sb.append("\t"
					+ res.getString(R.string.status)
					+ ": "
					+ ((value == VALUE_OK) ? res.getString(R.string.ok) : res
					.getString(R.string.problem)) + "\n");
			sb.append("\t"
					+ res.getString(R.string.acknowledged)
					+ ": "
					+ (acknowledged ? res.getString(R.string.yes) : res
					.getString(R.string.no)) + "\n");

			if (trigger != null) {
				sb.append(trigger.getSharableString(context));
			}

			return sb.toString();
		} else {
			return "";
		}
	}

} @DatabaseTable(tableName = "hostgroups")
public class HostGroup implements Comparable<HostGroup> {

	public static final long GROUP_ID_ALL = -1;

	/** Host ID */
	public static final String COLUMN_GROUPID = "groupid";
	@DatabaseField(id = true, columnName = COLUMN_GROUPID)
	private long groupId;

	/** Host name */
	public static final String COLUMN_NAME = "name";
	@DatabaseField(columnName = COLUMN_NAME)
	private String name;

	/** zabbix server */
	public static final String COLUMN_ZABBIXSERVER_ID = "zabbixserverid";
	@DatabaseField(columnName = COLUMN_ZABBIXSERVER_ID)
	private Long zabbixServerId;

	public HostGroup() {

	}

	public HostGroup(long groupId, String name) {
		this.groupId = groupId;
		this.name = name;
	}

	public long getGroupId() {
		return groupId;
	}

	public void setGroupId(long groupId) {
		this.groupId = groupId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return groupId + " " + name;
	}

	@Override
	public int compareTo(HostGroup another) {
		if (groupId > another.getGroupId())
			return 1;
		if (groupId < another.getGroupId())
			return -1;
		return 0;
	}

	public Long getZabbixServerId() {
		return zabbixServerId;
	}

	public void setZabbixServerId(Long zabbixServerId) {
		this.zabbixServerId = zabbixServerId;
	}

} @DatabaseTable(tableName = "host_hostgroup_relation")
public class HostHostGroupRelation {

	private static final String INDEX_HOST_GROUP = "host_group_idx";
	@DatabaseField(generatedId = true)
	private long id;
	/** Trigger ID */
	public static final String COLUMN_HOSTID = "hostid";
	@DatabaseField(uniqueIndexName = INDEX_HOST_GROUP, foreign = true, columnName = COLUMN_HOSTID)
	private Host host;
	/** Host group ID */
	public static final String COLUMN_GROUPID = "groupid";
	@DatabaseField(uniqueIndexName = INDEX_HOST_GROUP, foreign = true, columnName = COLUMN_GROUPID)
	private HostGroup group;

	public HostHostGroupRelation() {

	}

	public HostHostGroupRelation(Host host, HostGroup hostGroup) {
		this.host = host;
		this.group = hostGroup;
	}

	public Host getHost() {
		return host;
	}

	public void setHost(Host host) {
		this.host = host;
	}

	public HostGroup getGroup() {
		return group;
	}

	public void setGroup(HostGroup group) {
		this.group = group;
	}

} @DatabaseTable(tableName = "items")
public class Item implements Comparable<Item>, Sharable {

	public static int STATUS_ENABLED = 0;

	public static final String COLUMN_ITEMID = "itemid";
	@DatabaseField(id = true, columnName = COLUMN_ITEMID)
	long id;
	public static final String COLUMN_HOSTID = "hostid";
	@DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = COLUMN_HOSTID)
	Host host;
	public static final String COLUMN_VALUE_TYPE = "value_type";
	@DatabaseField(columnName = COLUMN_VALUE_TYPE)
	int valueType;
	public static final String COLUMN_DESCRIPTION = "description";
	public static final String COLUMN_DESCRIPTION_V2 = "name";
	@DatabaseField(columnName = COLUMN_DESCRIPTION)
	String description;
	public static final String COLUMN_LASTCLOCK = "lastclock";
	@DatabaseField(columnName = COLUMN_LASTCLOCK)
	long lastClock;
	public static final String COLUMN_LASTVALUE = "lastvalue";
	@DatabaseField(columnName = COLUMN_LASTVALUE)
	String lastValue;
	public static final String COLUMN_UNITS = "units";
	@DatabaseField(columnName = COLUMN_UNITS)
	String units;
	public static final String COLUMN_STATUS = "status";
	@DatabaseField(columnName = COLUMN_STATUS)
	int status;

	// only local
	Collection<HistoryDetail> historyDetails;

	public Item() {

	}

	public Item(long id, Host host, int valueType, String description,
			long lastClock, String lastValue, String units) {
		this.id = id;
		this.host = host;
		this.valueType = valueType;
		this.description = description;
		this.lastClock = lastClock;
		this.lastValue = lastValue;
		this.units = units;
	}

	public long getId() {
		return id;
	}

	public Host getHost() {
		return host;
	}

	public int getValueType() {
		return valueType;
	}

	public String getDescription() {
		String desc = description;
		desc = desc.replaceAll("&nbsp;", " ");
		return desc;
	}

	public long getLastClock() {
		return lastClock;
	}

	public String getLastValue() {
		return lastValue;
	}

	public String getUnits() {
		return units;
	}

	public Collection<HistoryDetail> getHistoryDetails() {
		return historyDetails;
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public void setId(long id) {
		this.id = id;
	}

	public void setHost(Host host) {
		this.host = host;
	}

	public void setValueType(int valueType) {
		this.valueType = valueType;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setLastClock(long lastClock) {
		this.lastClock = lastClock;
	}

	public void setLastValue(String lastValue) {
		this.lastValue = lastValue;
	}

	public void setUnits(String units) {
		this.units = units;
	}

	public void setHistoryDetails(Collection<HistoryDetail> historyDetails) {
		this.historyDetails = historyDetails;
	}

	@Override
	public String toString() {
		return "item " + getId() + ": " + getDescription();
	}

	@Override
	public int compareTo(Item another) {
		if (this.id > another.getId())
			return 1;
		return -1;
	}

	@Override
	public String getSharableString(Context context) {
		StringBuilder sb = new StringBuilder();
		Resources res = context.getResources();
		sb.append(res.getString(R.string.item) + ":\n");
		sb.append("\t" + res.getString(R.string.title) + ": "
				+ getDescription() + "\n");
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(lastClock);
		DateFormat dateFormatter = SimpleDateFormat.getDateTimeInstance(
				SimpleDateFormat.SHORT, SimpleDateFormat.SHORT,
				Locale.getDefault());
		sb.append("\t" + res.getString(R.string.latest_data) + ": " + lastValue
				+ units + " " + res.getString(R.string.at) + " "
				+ dateFormatter.format(cal.getTime()));
		return sb.toString();
	}
} @DatabaseTable(tableName = "screens")
public class Screen implements Comparable<Screen> {

	private static final String INDEX_SCREENID_HOST = "screen_host_idx";
	/** row ID */
	public static final String COLUMN_ID = "id";
	@DatabaseField(generatedId = true, columnName = COLUMN_ID)
	long id;
	/** Screen ID */
	public static final String COLUMN_SCREENID = "screenid";
	@DatabaseField(uniqueIndexName = INDEX_SCREENID_HOST, columnName = COLUMN_SCREENID)
	long screenId;
	/** Screen name */
	public static final String COLUMN_NAME = "name";
	@DatabaseField(columnName = COLUMN_NAME)
	String name;

	/** Host (needed for templates */
	public static final String COLUMN_HOST = "host";
	@DatabaseField(uniqueIndexName = INDEX_SCREENID_HOST, foreign = true, foreignAutoRefresh = true, columnName = COLUMN_HOST)
	Host host;

	/** zabbix server */
	public static final String COLUMN_ZABBIXSERVER_ID = "zabbixserverid";
	@DatabaseField(columnName = COLUMN_ZABBIXSERVER_ID)
	private Long zabbixServerId;

	Collection<Graph> graphs;

	public Screen() {
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public long getScreenId() {
		return screenId;
	}

	public String getName() {
		return name;
	}

	public Collection<Graph> getGraphs() {
		return graphs;
	}

	public void setGraphs(Collection<Graph> graphs) {
		this.graphs = graphs;
	}

	public void setScreenId(long screenId) {
		this.screenId = screenId;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int compareTo(Screen another) {
		if (another.getScreenId() < screenId)
			return 1;
		if (another.getScreenId() > screenId)
			return -1;
		if(!another.getHost().equals(host))
			return -1;
		return 0;
	}

	public Long getZabbixServerId() {
		return zabbixServerId;
	}

	public void setZabbixServerId(Long zabbixServerId) {
		this.zabbixServerId = zabbixServerId;
	}

	public Host getHost() {
		return host;
	}

	public void setHost(Host host) {
		this.host = host;
	}
} @DatabaseTable(tableName = "screenitems")
public class ScreenItem {

	private static final String INDEX_SCREENITEMID_HOST = "screenitem_host_idx";
	/** row ID */
	public static final String COLUMN_ID = "id";
	@DatabaseField(generatedId = true, columnName = COLUMN_ID)
	long id;
	/** screen Item ID */
	public static final String COLUMN_SCREENITEMID = "screenitemid";
	@DatabaseField(uniqueIndexName = INDEX_SCREENITEMID_HOST, columnName = COLUMN_SCREENITEMID)
	long screenItemId;
	/** screen ID */
	public static final String COLUMN_SCREENID = "screenid";
	@DatabaseField(columnName = COLUMN_SCREENID, index = true)
	long screenId;
	/** graph id */
	public static final String COLUMN_RESOURCEID = "resourceid";
	@DatabaseField(columnName = COLUMN_RESOURCEID)
	long resourceId;
	/** host (used for template screens) */
	public static final String COLUMN_HOST = "host";
	@DatabaseField(foreign = true, foreignAutoRefresh = true, uniqueIndexName = INDEX_SCREENITEMID_HOST, columnName = COLUMN_HOST)
	Host host;
	/** real graph id (used for template screens) */
	public static final String COLUMN_REAL_RESOURCEID = "real_resourceid";
	@DatabaseField(columnName = COLUMN_REAL_RESOURCEID)
	Long realResourceId;

	public ScreenItem() {

	}

	public long getScreenItemId() {
		return screenItemId;
	}

	public long getScreenId() {
		return screenId;
	}

	public long getResourceId() {
		return resourceId;
	}

	public void setScreenItemId(long screenItemId) {
		this.screenItemId = screenItemId;
	}

	public void setScreenId(long screenId) {
		this.screenId = screenId;
	}

	public void setResourceId(long resourceId) {
		this.resourceId = resourceId;
	}

	public Host getHost() {
		return host;
	}

	public void setHost(Host host) {
		this.host = host;
	}

	public Long getRealResourceId() {
		return realResourceId;
	}

	public void setRealResourceId(Long realResourceId) {
		this.realResourceId = realResourceId;
	}
} @DatabaseTable(tableName = "triggers")
public class Trigger implements Comparable<Trigger>, Sharable {

	public static final int VALUE_PROBLEM = 1;
	public static final int VALUE_OK = 0;
	public static int STATUS_ENABLED = 0;

	public static final String COLUMN_TRIGGERID = "triggerid";
	@DatabaseField(id = true, columnName = COLUMN_TRIGGERID)
	long id;
	public static final String COLUMN_DESCRIPTION = "description";
	@DatabaseField(columnName = COLUMN_DESCRIPTION)
	String description;
	public static final String COLUMN_EXPRESSION = "expression";
	@DatabaseField(columnName = COLUMN_EXPRESSION)
	String expression;
	public static final String COLUMN_COMMENTS = "comments";
	@DatabaseField(columnName = COLUMN_COMMENTS)
	String comments;
	public static final String COLUMN_LASTCHANGE = "lastchange";
	@DatabaseField(columnName = COLUMN_LASTCHANGE)
	long lastChange;
	public static final String COLUMN_PRIORITY = "priority";
	@DatabaseField(columnName = COLUMN_PRIORITY, index = true)
	TriggerSeverity priority;
	public static final String COLUMN_STATUS = "status";
	@DatabaseField(columnName = COLUMN_STATUS)
	int status;
	public static final String COLUMN_VALUE = "value";
	@DatabaseField(columnName = COLUMN_VALUE)
	int value;
	public static final String COLUMN_URL = "url";
	@DatabaseField(columnName = COLUMN_URL)
	String url;
	public static final String COLUMN_ITEMID = "itemid";
	@DatabaseField(columnName = COLUMN_ITEMID, foreign = true, foreignAutoRefresh = true)
	Item item;
	public static final String COLUMN_ENABLED = "enabled";
	@DatabaseField(columnName = COLUMN_ENABLED)
	boolean enabled;

	// only local
	@DatabaseField
	String hostNames;

	public Trigger() {

	}

	public Trigger(long id, String description, String expression,
			String comments, long lastChange, TriggerSeverity priority,
			int status, int value, String url) {
		this.id = id;
		this.description = description;
		this.expression = expression;
		this.comments = comments;
		this.lastChange = lastChange;
		this.priority = priority;
		this.status = status;
		this.value = value;
		this.url = url;
	}

	@Override
	public int compareTo(Trigger another) {
		if (id == another.getId())
			return 0;
		if (lastChange < another.getLastChange())
			return 1;
		if (lastChange > another.getLastChange())
			return -1;
		if (item == null)
			return 1;
		if (another.getItem() == null)
			return -1;
		if (item.getId() > another.getItem().getId())
			return 1;
		else
			return -1;
	}

	public String getComments() {
		return comments;
	}

	public String getDescription() {
		String desc = description;
		if (hostNames != null && hostNames.length() > 0)
			desc = desc.replaceAll("\\{HOSTNAME\\}", hostNames);
		desc = desc.replaceAll("&nbsp;", " ");
		return desc;
	}

	public String getExpression() {
		String expr = expression;
		expr = expr.replaceAll("&nbsp;", " ");
		return expr;
	}

	public String getHostNames() {
		return hostNames;
	}

	public long getId() {
		return id;
	}

	public Item getItem() {
		return item;
	}

	public long getLastChange() {
		return lastChange;
	}

	public TriggerSeverity getPriority() {
		return priority;
	}

	public int getStatus() {
		return status;
	}

	public String getUrl() {
		return url;
	}

	public int getValue() {
		return value;
	}

	public boolean isEnabled() {
		return enabled;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public void setExpression(String expression) {
		this.expression = expression;
	}

	public void setHostNames(String hostNames) {
		this.hostNames = hostNames;
	}

	public void setId(long id) {
		this.id = id;
	}

	public void setItem(Item item) {
		this.item = item;
	}

	public void setLastChange(long lastChange) {
		this.lastChange = lastChange;
	}

	public void setPriority(TriggerSeverity priority) {
		this.priority = priority;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setValue(int value) {
		this.value = value;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("id=").append(id);
		sb.append(", ").append("description=").append(getDescription());
		sb.append(", ").append("expression=").append(getExpression());
		sb.append(", ").append("comments=").append(comments);
		DateFormat dateFormatter = SimpleDateFormat.getDateTimeInstance(
				SimpleDateFormat.DEFAULT, SimpleDateFormat.DEFAULT, Locale.US);
		sb.append(", ").append("lastchange=")
				.append(dateFormatter.format(lastChange));
		sb.append(", ").append("priority=").append(priority);
		sb.append(", ").append("status=").append(status);
		sb.append(", ").append("value=").append(value);
		sb.append(", ").append("url=").append(url);
		return sb.toString();
	}

	@Override
	public String getSharableString(Context context) {
		StringBuilder sb = new StringBuilder();
		Resources res = context.getResources();
		sb.append(res.getString(R.string.trigger) + ":\n");
		sb.append("\t" + res.getString(R.string.host) + ": " + hostNames + "\n");
		sb.append("\t" + res.getString(R.string.trigger) + ": "
				+ getDescription() + "\n");
		sb.append("\t" + res.getString(R.string.severity) + ": "
				+ res.getString(priority.getNameResourceId()) + "\n");
		sb.append("\t" + res.getString(R.string.expression) + ": "
				+ getExpression() + "\n");

		if (item != null) {
			sb.append(item.getSharableString(context));
		}

		return sb.toString();
	}

} @DatabaseTable(tableName = "trigger_hostgroup_relation")
public class TriggerHostGroupRelation {

	@DatabaseField(generatedId = true)
	private long id;
	/** Trigger ID */
	public static final String COLUMN_TRIGGERID = "triggerid";
	@DatabaseField(uniqueIndexName = "trigger_group_idx", foreign = true, columnName = COLUMN_TRIGGERID)
	private Trigger trigger;
	/** Host group ID */
	public static final String COLUMN_GROUPID = "groupid";
	@DatabaseField(uniqueIndexName = "trigger_group_idx", foreign = true, columnName = COLUMN_GROUPID)
	private HostGroup group;

	public TriggerHostGroupRelation() {

	}

	public TriggerHostGroupRelation(Trigger trigger, HostGroup hostGroup) {
		this.trigger = trigger;
		this.group = hostGroup;
	}

	public Trigger getTrigger() {
		return trigger;
	}

	public void setTrigger(Trigger trigger) {
		this.trigger = trigger;
	}

	public HostGroup getGroup() {
		return group;
	}

	public void setGroup(HostGroup group) {
		this.group = group;
	}

} public class ZaxPreferences {

	private SharedPreferences mPref;

	public static ZaxPreferences getInstance(Context context) {
		return (new ZaxPreferences(context));
	}

	private ZaxPreferences(Context context) {
		refresh(context);
	}

	public int getWidgetRefreshInterval() {
		try {
			return Integer.parseInt(mPref.getString(
					"widget_refresh_interval_mins", "15"));
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	public void registerOnSharedPreferenceChangeListener(
			OnSharedPreferenceChangeListener listener) {
		mPref.registerOnSharedPreferenceChangeListener(listener);
	}

	public void unregisterOnSharedPreferenceChangeListener(
			OnSharedPreferenceChangeListener listener) {
		mPref.unregisterOnSharedPreferenceChangeListener(listener);
	}

	public boolean isDarkTheme() {
		return mPref.getBoolean("dark_theme", false);
	}

	public String getPersistedServerName(){
		return mPref.getString("server_name", "");
	}

	public void setPersistedServerName(String name){
		Editor edit = mPref.edit();
		edit.putString("server_name",name);
	}

	public long getServerSelection() {
		return mPref.getLong("server_selection", 0);
	}

	public void setServerSelection(long selection) {
		Editor edit = mPref.edit();
		edit.putLong("server_selection", selection);
		edit.commit();
	}

	public void refresh(Context context) {
		SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		mPref = pref;
	}

	public boolean hasOldServerPreferences() {
		if (mPref.getString("zabbix_url", null) != null) {
			return true;
		}
		return false;
	}

	public void migrateServerPreferences(Context context, long id) {
		ZaxServerPreferences p = new ZaxServerPreferences(context, id, true);
		p.savePrefs();

		refresh(context);
		mPref.edit().remove("zabbix_url").commit();
	}

	public boolean isOldNotificationIcons() {
		return mPref.getBoolean("zabbix_push_old_icons", false);
	}

	public boolean isPushEnabled() {
		return mPref.getBoolean("pubnub_push_enabled", mPref.getBoolean("zabbix_push_enabled",false));
	}

	public String getPushRingtone() {
		return mPref.getString("zabbix_push_ringtone", null);
	}

	public String getPushOkRingtone(){
		return mPref.getString("push_ok_ringtone", null);
	}

	public String getPushSubscribeKey() {
		return mPref.getString("pubnub_push_subscribe_key", mPref.getString("zabbix_push_subscribe_key", "")).trim();
	}

	public void setWidgetServer(int mAppWidgetId, long id) {
		Editor edit = mPref.edit();
		edit.putLong("widget_server_"+mAppWidgetId, id);
		edit.commit();
		Log.d("ZaxPreferences", "widget server="+mAppWidgetId+"="+id);
	}

	public long getWidgetServer(int mAppWidgetId) {
		Log.d("ZaxPreferences", "get widget server from "+mAppWidgetId+"="+mPref.getLong("widget_server_"+mAppWidgetId, -1));

		return mPref.getLong("widget_server_"+mAppWidgetId, -1);
	}

	public String getGCMSenderID() {
		return mPref.getString("gcm_sender_id", "");
	}

	public void setTokenSentToServer(boolean status){
		mPref.edit().putBoolean("sent_token_to_server",status);
	}

	public boolean isTokenSentToServer(){
		return mPref.getBoolean("sent_token_to_server",false);
	}

	public String getGCMServerUrl() {
		return mPref.getString("gcm_server_url", "");
	}

	public boolean isVibrate() {return mPref.getBoolean("vibrate",true);};
} public class ZaxServerPreferences {

	private final SharedPreferences mPref;
	private final long serverId;

	public ZaxServerPreferences(Context context, long serverId, boolean notLoadPrefs) {
		SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		mPref = pref;
		this.serverId = serverId;

		if (!notLoadPrefs) loadPrefs();
	}

	private void loadPrefs() {
		Editor edit = mPref.edit();
		edit.putString("zabbix_url", getZabbixUrl());
		edit.putString("zabbix_username", getUsername());
		edit.putString("zabbix_password", getPassword());
		edit.putBoolean("http_auth_enabled", isHttpAuthEnabled());
		edit.putString("http_auth_username", getHttpAuthUsername());
		edit.putString("http_auth_password", getHttpAuthPassword());
		edit.commit();
	}

	public void savePrefs() {
		Editor edit = mPref.edit();
		edit.putString(serverId + "zabbix_url", mPref.getString("zabbix_url", ""));
		edit.putString(serverId + "zabbix_username", mPref.getString("zabbix_username", ""));
		edit.putString(serverId + "zabbix_password", mPref.getString("zabbix_password", ""));
		edit.putBoolean(serverId + "http_auth_enabled", mPref.getBoolean("http_auth_enabled", false));
		edit.putString(serverId + "http_auth_username", mPref.getString("http_auth_username", ""));
		edit.putString(serverId + "http_auth_password", mPref.getString("http_auth_password", ""));
		edit.commit();
	}

	public boolean isConfigurated() {
		return !(getUsername().length() == 0)
				&& !(getZabbixUrl().length() == 0);
	}

	public String getUsername() {
		Log.d("ZaxServerPreferences", "aaa=" + serverId);
		return mPref.getString(serverId + "zabbix_username", "");
	}

	public String getPassword() {
		return mPref.getString(serverId + "zabbix_password", "");
	}

	public boolean isHttpAuthEnabled() {
		return mPref.getBoolean(serverId + "http_auth_enabled", false);
	}

	public String getHttpAuthUsername() {
		return mPref.getString(serverId + "http_auth_username", "");
	}

	public String getHttpAuthPassword() {
		return mPref.getString(serverId + "http_auth_password", "");
	}

	public String getZabbixUrl() {
		return mPref.getString(serverId + "zabbix_url", "");
	}

	/**
	 * Checks whether the server settings have been altered by the user
	 *
	 * @return true: the server settings are still default
	 */
	public boolean isDefault() {
		String url = mPref.getString("zabbix_url", "");
		return (url.equals("http://zabbix.company.net/zabbix"))
				|| (url == null) || url.equals("");
	}

	public void registerOnSharedPreferenceChangeListener(
			OnSharedPreferenceChangeListener listener) {
		mPref.registerOnSharedPreferenceChangeListener(listener);
	}

	public void unregisterOnSharedPreferenceChangeListener(
			OnSharedPreferenceChangeListener listener) {
		mPref.unregisterOnSharedPreferenceChangeListener(listener);
	}

	public void setZabbixAPIVersion(ZabbixAPIVersion version) {
		Editor edit = mPref.edit();
		edit.putInt("zabbix_api_version", version.getValue());
		edit.commit();
	}

	public ZabbixAPIVersion getZabbixAPIVersion() {
		return ZabbixAPIVersion.get(mPref.getInt("zabbix_api_version", ZabbixAPIVersion.API_1_3.getValue()));
	}


} public class JsonObjectReader {
	private final JsonParser parser;
	private boolean isParsed;

	/**
	 * @param parser
	 */
	public JsonObjectReader(JsonParser parser) {
		this.parser = parser;
	}

	/**
	 * reads the json object until its end. works recursively.
	 * 
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public void finishParsing() throws JsonParseException, IOException {
		if (isParsed)
			return;

		int offen = 1;
		do {
			JsonToken tk = parser.nextToken();
			if (tk == JsonToken.START_OBJECT)
				offen++;
			else if (tk == JsonToken.END_OBJECT)
				offen--;
		} while (offen > 0);
		parser.nextToken();
		isParsed = true;
	}

	/**
	 * @return current property
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public String getCurrentName() throws JsonParseException, IOException {
		return parser.getCurrentName();
	}

	/**
	 * @return JSon array or object reader for the current property
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public JsonArrayOrObjectReader getJsonArrayOrObjectReader()
			throws JsonParseException, IOException {
		boolean ok = false;
		if (parser.getCurrentToken() == JsonToken.START_ARRAY
				|| parser.getCurrentToken() == JsonToken.START_OBJECT) {
			ok = true;
		} else {
			parser.nextToken();
			if (parser.getCurrentToken() == JsonToken.START_ARRAY
					|| parser.getCurrentToken() == JsonToken.START_OBJECT) {
				ok = true;
			}
		}
		if (!ok) {
			Log.e("JsonObjectReader", "token: " + parser.getCurrentToken());
			Log.e("JsonObjectReader", "name: " + parser.getCurrentName());
			Log.e("JsonObjectReader", "text: " + parser.getText());
			throw new IllegalStateException();
		}
		return new JsonArrayOrObjectReader(parser);
	}

	/**
	 * @return value of current property as string
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public String getText() throws JsonParseException, IOException {
		return parser.getText();
	}

	/**
	 * @return true, if object was read to the end.
	 */
	public boolean isParsed() {
		return isParsed;
	}

	/**
	 * skips current property
	 * 
	 * @return true, if yet another property exists. false, if the object was
	 *         read to the end.
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public boolean nextProperty() throws JsonParseException, IOException {
		if (isParsed)
			return false;

		JsonToken tk;
		do {
			tk = parser.nextToken();
			if (tk == JsonToken.START_ARRAY || tk == JsonToken.START_OBJECT) {
				parser.skipChildren();
			}
			if (tk == JsonToken.END_OBJECT) {
				isParsed = true;
				return false;
			}
		} while (tk != JsonToken.FIELD_NAME);
		return true;
	}

	/**
	 * jumps to the next json token (low level)
	 * 
	 * @return false, if the object was read to the end.
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public boolean nextToken() throws JsonParseException, IOException {
		if (isParsed)
			return false;

		JsonToken tk = parser.nextToken();
		if (tk == JsonToken.END_OBJECT) {
			isParsed = true;
		}
		return !isParsed();
	}

	/**
	 * reads to the next property
	 * 
	 * @return false, if the object was read to the end
	 * @throws JsonParseException
	 * @throws IOException
	 */
	public boolean nextValueToken() throws JsonParseException, IOException {
		if (isParsed)
			return false;

		JsonToken tk = parser.nextToken();
		if (tk == JsonToken.END_OBJECT) {
			isParsed = true;
			return false;
		}
		if (tk == JsonToken.FIELD_NAME) {
			return nextToken();
		}
		return true;
	}

}
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.util.Log;
import android.util.Patterns;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.inovex.zabbixmobile.R;
import com.inovex.zabbixmobile.exceptions.FatalException;
import com.inovex.zabbixmobile.exceptions.FatalException.Type;
import com.inovex.zabbixmobile.exceptions.ZabbixLoginRequiredException;
import com.inovex.zabbixmobile.model.Application;
import com.inovex.zabbixmobile.model.ApplicationItemRelation;
import com.inovex.zabbixmobile.model.Cache.CacheDataType;
import com.inovex.zabbixmobile.model.Event;
import com.inovex.zabbixmobile.model.Graph;
import com.inovex.zabbixmobile.model.GraphItem;
import com.inovex.zabbixmobile.model.HistoryDetail;
import com.inovex.zabbixmobile.model.Host;
import com.inovex.zabbixmobile.model.HostGroup;
import com.inovex.zabbixmobile.model.HostHostGroupRelation;
import com.inovex.zabbixmobile.model.Item;
import com.inovex.zabbixmobile.model.Screen;
import com.inovex.zabbixmobile.model.ScreenItem;
import com.inovex.zabbixmobile.model.Trigger;
import com.inovex.zabbixmobile.model.TriggerHostGroupRelation;
import com.inovex.zabbixmobile.model.TriggerSeverity;
import com.inovex.zabbixmobile.model.ZaxPreferences;
import com.inovex.zabbixmobile.model.ZaxServerPreferences;
import com.inovex.zabbixmobile.util.JsonArrayOrObjectReader;
import com.inovex.zabbixmobile.util.JsonObjectReader;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
					key_ = itemReader.getText();
				} else if (propName.equals("applications")) {
					applications = importApplicationsFromIdStream(itemReader
							.getJsonArrayOrObjectReader());
				} else {
					itemReader.nextProperty();
				}
			}
			// if applicable replace placeholder
			String description = item.getDescription();
			if (description != null && description.matches(".*\\$[0-9].*")) {
				if (key_ != null && key_.indexOf('[') != -1) {
					String[] keys = key_.substring(key_.indexOf('[') + 1,
							key_.indexOf(']')).split(",");
					for (int ix = 0; ix < keys.length; ix++) {
						description = description.replace("$" + (ix + 1),
								keys[ix]);
					}
				}
			}
			item.setDescription(description);

			itemsPerBatch.add(item);
			itemsComplete.add(item);
			if (itemsPerBatch.size() >= RECORDS_PER_INSERT_BATCH) {
				databaseHelper.insertItems(itemsPerBatch);
				itemsPerBatch.clear();
			}

			if (item.getHost() != null
					&& (applications == null || applications.isEmpty())) {
				// If no application has been found for this particular event,
				// we create an "other" application
				long otherId = item.getHost().getId() * (-1);
				Application other = databaseHelper.getApplicationById(otherId);
				if (other == null) {
					other = new Application();
					other.setHost(item.getHost());
					other.setId(otherId);
					other.setName(mContext.getResources().getString(
							R.string.other));
					ArrayList<Application> apps = new ArrayList<Application>();
					apps.add(other);
					databaseHelper.insertApplications(apps);
				}
				applications.add(other);
			}
			// insert application item relations
			for (Application app : applications) {
				app.setHost(item.getHost());
				applicationItemRelations.add(new ApplicationItemRelation(app,
						item.getHost(), item));
			}
			if (applicationItemRelations.size() >= RECORDS_PER_INSERT_BATCH) {
				databaseHelper
						.insertApplicationItemRelations(applicationItemRelations);
				applicationItemRelations.clear();
			}
			i++;
			if (task != null && numItems > 0)
				task.updateProgress(20 + ((i * 80) / numItems));
		}
		// insert the last batch of events
		databaseHelper.insertItems(itemsPerBatch);
		databaseHelper.insertApplicationItemRelations(applicationItemRelations);
		return itemsComplete;
	}

	/**
	 * Imports all items for a particular host from Zabbix.
	 *
	 * @param hostId
	 *            host ID to filter the applications by; null: no filtering
	 * @param task
	 *            task to be notified about progress
	 * @throws FatalException
	 * @throws ZabbixLoginRequiredException
	 */
	public void importItemsByHostId(Long hostId, RemoteAPITask task)
			throws FatalException, ZabbixLoginRequiredException {
		if (databaseHelper.isCached(CacheDataType.ITEM, hostId))
			return;

		databaseHelper.deleteItemsByHostId(hostId);

		try {
			// count of items
			JSONObject params = new JSONObject();
			params.put("countOutput", 1);
			if (hostId != null)
				params.put("hostids", new JSONArray().put(hostId));

			JSONObject result = _queryBuffer("item.get", params);
			// Zabbix does not support limit when countOutput is set
			int numItems = Math.min(ZabbixConfig.ITEM_GET_LIMIT,
					getOutputCount(result));

			params = new JSONObject();
			params.put("output", "extend")
					.put("limit", ZabbixConfig.ITEM_GET_LIMIT)
					.put(mServerPreferences.getZabbixAPIVersion().isGreater1_4() ? "selectApplications"
							: "select_applications", "refer");
			if (hostId != null)
				params.put("hostids", new JSONArray().put(hostId));
			JsonArrayOrObjectReader items = _queryStream("item.get", params);
			importItemsFromStream(items, task, numItems, false);
			items.close();

			// Log.d(TAG, _queryBuffer("item.get", params).toString());

		} catch (JSONException e) {
			throw new FatalException(Type.INTERNAL_ERROR, e);
		} catch (IOException e) {
			throw new FatalException(Type.INTERNAL_ERROR, e);
		}

		databaseHelper.setCached(CacheDataType.ITEM, hostId);

	}

	private ArrayList<ScreenItem> parseScreenItemsFromStream(JsonArrayOrObjectReader jsonReader)