package com.commafeed.backend.dao;

import java.util.Date;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.SessionFactory;

import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.QFeed;
import com.commafeed.backend.model.QFeedSubscription;
import com.commafeed.backend.model.QUser;
import com.google.common.collect.Iterables;
import com.mysema.query.BooleanBuilder;
import com.mysema.query.jpa.hibernate.HibernateQuery;
import com.mysema.query.jpa.hibernate.HibernateSubQuery;

@Singleton
public class FeedDAO extends GenericDAO<Feed> {

	private QFeed feed = QFeed.feed;

	@Inject
	public FeedDAO(SessionFactory sessionFactory) {
		super(sessionFactory);
	}

	public List<Feed> findNextUpdatable(int count, Date lastLoginThreshold) {
		BooleanBuilder disabledDatePredicate = new BooleanBuilder();
		disabledDatePredicate.or(feed.disabledUntil.isNull());
		disabledDatePredicate.or(feed.disabledUntil.lt(new Date()));

		HibernateQuery query = null;
		if (lastLoginThreshold != null) {
			QFeedSubscription subs = QFeedSubscription.feedSubscription;
			QUser user = QUser.user;
			query = newQuery().from(subs);
			query.join(subs.feed, feed).join(subs.user, user).where(disabledDatePredicate, user.lastLogin.gt(lastLoginThreshold));
		} else {
			query = newQuery().from(feed);
			query.where(disabledDatePredicate);
		}

		return query.orderBy(feed.disabledUntil.asc()).limit(count).distinct().list(feed);
	}

	public Feed findByUrl(String normalizedUrl) {
		List<Feed> feeds = newQuery().from(feed).where(feed.normalizedUrlHash.eq(DigestUtils.sha1Hex(normalizedUrl))).list(feed);
		Feed feed = Iterables.getFirst(feeds, null);
		if (feed != null && StringUtils.equals(normalizedUrl, feed.getNormalizedUrl())) {
			return feed;
		}
		return null;
	}

	public List<Feed> findByTopic(String topic) {
		return newQuery().from(feed).where(feed.pushTopicHash.eq(DigestUtils.sha1Hex(topic))).list(feed);
	}

	public List<Feed> findWithoutSubscriptions(int max) {
		QFeedSubscription sub = QFeedSubscription.feedSubscription;
		return newQuery().from(feed).where(new HibernateSubQuery().from(sub).where(sub.feed.eq(feed)).notExists()).limit(max).list(feed);
		// return newQuery().from(feed).leftJoin(feed.subscriptions, sub).where(sub.id.isNull()).limit(max).list(feed);
	}
}

@@ -515,49 +515,8 @@
 s;%0D%0A
-import com.mysema.query.BooleanBuilder;%0D%0A
 impo
@@ -900,96 +900,68 @@
 %0D%0A%09%09
-BooleanBuilder disabledDatePredicate = new BooleanBuild
+HibernateQuery query = newQu
 er
+y
 ()
-;%0D%0A%09%09disabledDatePredicate.or
+.from(feed);%0D%0A%09%09query.where
 (fee
@@ -988,35 +988,8 @@
 ll()
-);%0D%0A%09%09disabledDatePredicate
 .or(
@@ -1026,45 +1026,14 @@
 ()))
+)
 ;%0D%0A%0D%0A
-%09%09HibernateQuery query = null;%0D%0A
 %09%09if
@@ -1163,73 +1163,90 @@
 r;%0D%0A
+%0D%0A
 %09%09%09
-query = newQuery().from(subs);%0D%0A%09%09%09query.join(subs.feed, feed)
+HibernateSubQuery subQuery = new HibernateSubQuery().from(subs);%0D%0A%09%09%09subQuery
 .joi
@@ -1274,31 +1274,8 @@
 ere(
-disabledDatePredicate, 
 user
@@ -1317,89 +1317,38 @@
 %0D%0A%09%09
-%7D else %7B%0D%0A%09%09%09query = newQuery().from(feed);%0D%0A%09%09%09query.where(disabledDatePredicate
+%09query.where(subQuery.exists()
 );%0D%0A

rewrite query using subqueries