package net.vexelon.currencybg.srv;

import java.io.IOException;
import java.util.List;
import java.util.Map;

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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import net.vexelon.currencybg.srv.db.DataSource;
import net.vexelon.currencybg.srv.db.DataSourceException;
import net.vexelon.currencybg.srv.db.DataSourceInterface;
import net.vexelon.currencybg.srv.db.models.CurrencyData;
import net.vexelon.currencybg.srv.db.models.Sources;
import net.vexelon.currencybg.srv.remote.Source;
import net.vexelon.currencybg.srv.remote.SourceException;
import net.vexelon.currencybg.srv.reports.ConsoleReporter;

/**
 * Fetches currencies from remote server and imports them into the database.
 *
 */
public class Heartbeat implements Runnable {

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

	@Override
	public void run() {
		log.info("Downloading rates from sources ...");
		try {
			/*
			 * TODO: Fetch all sources from db
			 */
			List<Sources> sourcesList = Lists.newArrayList();
			sourcesList.add(Sources.TAVEX);

			/*
			 * Fetch currencies for every active source
			 */
			for (Sources sources : sourcesList) {
				try {
					// TODO: add proper reporter
					final ConsoleReporter reporter = new ConsoleReporter();
					sources.newInstance(reporter).getRates(new Source.Callback() {

						@Override
						public void onFailed(Exception e) {
							log.error("Source download failed!", e);

							if (!reporter.isEmpty()) {
								try {
									reporter.send();
								} catch (IOException ioe) {
									log.error("Failed sending report!", ioe);
								}
							}
						}

						@Override
						public void onCompleted(List<CurrencyData> currencyDataList) {
							log.debug("Source download succcesful.");

							// TODO Remove this map and use another
							Map<Integer, List<CurrencyData>> sourceToCurrencyMap = Maps.newHashMap();
							sourceToCurrencyMap.put(Sources.TAVEX.getID(), currencyDataList);

							if (log.isTraceEnabled()) {
								for (CurrencyData currency : currencyDataList) {
									log.trace(currency.toString());
								}
							}

							log.debug("Importing downloaded rates in database ...");
							try (final DataSourceInterface dataSource = new DataSource()) {
								dataSource.connect();
								// TODO: use another method without Map
								dataSource.addRates(sourceToCurrencyMap);
							} catch (IOException | DataSourceException e) {
								log.error("Could not connect to database!", e);
							}
						}
					});
				} catch (SourceException e) {
					log.error("Failed fetching rates from '{}' source!", sources.name(), e);
				}
			}
		} catch (Throwable t) {
			/*
			 * The executor swallows exceptions, so catch Throwable instead.
			 * 
			 * @see http://stackoverflow.com/a/24902026
			 */
			log.error("Fatal hearbeat error!", t);
		}
	}
}

@@ -1125,16 +1125,49 @@
 .TAVEX);
+%0A%09%09%09sourcesList.add(Sources.BNB);
 %0A%0A%09%09%09/*%0A
@@ -1367,24 +1367,57 @@
 ter();%0A%09%09%09%09%09
+final Source newSourceInstance = 
 sources.newI
@@ -1433,16 +1433,40 @@
 eporter)
+;%0A%09%09%09%09%09newSourceInstance
 .getRate
@@ -1568,17 +1568,22 @@
 .error(%22
-S
+%7B%7D - s
 ource do
@@ -1602,14 +1602,42 @@
 d!%22,
+ newSourceInstance.getName(),
  e);%0A
-%0A
 %09%09%09%09
@@ -1758,24 +1758,29 @@
 %09log.error(%22
+%7B%7D - 
 Failed sendi
@@ -1791,16 +1791,45 @@
 eport!%22,
+ newSourceInstance.getName(),
  ioe);%0A%09
@@ -1958,17 +1958,22 @@
 .debug(%22
-S
+%7B%7D - s
 ource do
@@ -1991,16 +1991,45 @@
 cesful.%22
+, newSourceInstance.getName()
 );%0A%0A%09%09%09%09
@@ -2397,17 +2397,22 @@
 .debug(%22
-I
+%7B%7D - i
 mporting
@@ -2441,24 +2441,53 @@
 atabase ...%22
+, newSourceInstance.getName()
 );%0A%09%09%09%09%09%09%09tr

Add BNB test source