package com.commafeed.backend;

import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.commafeed.backend.dao.FeedDAO;
import com.commafeed.backend.dao.FeedDAO.FeedCount;
import com.commafeed.backend.dao.FeedEntryDAO;
import com.commafeed.backend.dao.FeedSubscriptionDAO;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedSubscription;
import com.google.common.collect.Lists;

public class DatabaseCleaner {

	private static Logger log = LoggerFactory.getLogger(DatabaseCleaner.class);

	@Inject
	FeedDAO feedDAO;

	@Inject
	FeedEntryDAO feedEntryDAO;

	@Inject
	FeedSubscriptionDAO feedSubscriptionDAO;

	public long cleanFeedsWithoutSubscriptions() {

		long total = 0;
		int deleted = -1;
		do {
			deleted = feedDAO.deleteWithoutSubscriptions(10);
			total += deleted;
			log.info("removed {} feeds without subscriptions", total);
		} while (deleted != 0);
		log.info("cleanup done: {} feeds without subscriptions deleted", total);
		return total;
	}

	public long cleanEntriesWithoutFeeds() {

		long total = 0;
		int deleted = -1;
		do {
			deleted = feedEntryDAO.deleteWithoutFeeds(100);
			total += deleted;
			log.info("removed {} entries without feeds", total);
		} while (deleted != 0);
		log.info("cleanup done: {} entries without feeds deleted", total);
		return total;
	}

	public long cleanEntriesOlderThan(long value, TimeUnit unit) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MINUTE, -1 * (int) unit.toMinutes(value));

		long total = 0;
		int deleted = -1;
		do {
			deleted = feedEntryDAO.delete(cal.getTime(), 100);
			total += deleted;
			log.info("removed {} entries", total);
		} while (deleted != 0);
		log.info("cleanup done: {} entries deleted", total);
		return total;
	}

	public long cleanDuplicateFeeds() {
		long total = 0;
		int deleted = -1;
		do {
			List<FeedCount> fcs = feedDAO.findDuplicates(0, 10, 1);
			deleted = fcs.size();

			List<Thread> threads = Lists.newArrayList();
			for (final FeedCount fc : fcs) {
				Thread thread = new Thread() {
					public void run() {
						Feed into = feedDAO.findById(fc.feeds.get(0).getId());
						List<Feed> feeds = Lists.newArrayList();
						for (Feed feed : fc.feeds) {
							feeds.add(feedDAO.findById(feed.getId()));
						}
						mergeFeeds(into, feeds);
					};
				};
				thread.start();
				threads.add(thread);
			}
			for (Thread thread : threads) {
				try {
					thread.join();
				} catch (InterruptedException e) {
					log.error(e.getMessage(), e);
				}
			}
			total += deleted;
			log.info("merged {} feeds", total);
		} while (deleted != 0);
		log.info("cleanup done: {} feeds merged", total);
		return total;
	}

	public void mergeFeeds(Feed into, List<Feed> feeds) {
		for (Feed feed : feeds) {
			if (into.getId().equals(feed.getId())) {
				continue;
			}
			List<FeedSubscription> subs = feedSubscriptionDAO.findByFeed(feed);
			for (FeedSubscription sub : subs) {
				sub.setFeed(into);
			}
			feedSubscriptionDAO.saveOrUpdate(subs);
			feedDAO.deleteRelationships(feed);
			feedDAO.delete(feed);
		}
		feedDAO.saveOrUpdate(into);
	}
}

@@ -507,16 +507,83 @@
 ption;%0D%0A
+import com.commafeed.backend.services.ApplicationSettingsService;%0D%0A
 import c
@@ -854,24 +854,93 @@
 tionDAO;%0D%0A%0D%0A
+%09@Inject%0D%0A%09ApplicationSettingsService applicationSettingsService;%0D%0A%0D%0A
 %09public long
@@ -2195,24 +2195,31 @@
 cs = feedDAO
+%0D%0A%09%09%09%09%09
 .findDuplica
@@ -2225,18 +2225,84 @@
 ates(0, 
-10
+applicationSettingsService.get()%0D%0A%09%09%09%09%09%09%09.getDatabaseUpdateThreads()
 , 1);%0D%0A%09

use settings instead of hardcoded value