/*
 * Copyright (c) 2006-2009 OrangeSignal.com All rights reserved.
 */

package jp.sourceforge.orangesignal.ta.dataset.loader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.sourceforge.orangesignal.ta.dataset.PriceData;
import jp.sourceforge.orangesignal.ta.dataset.TimeSeriesDataset;
import jp.sourceforge.orangesignal.ta.dataset.TimeSeriesDataset.Interval;

/**
 * 価格データファイルからデータセットをロードするデータセットローダークラスを提供します。
 * 
 * @author 杉澤 浩二
 * @since 1.1
 */
public class FileDatasetLoader implements DatasetLoader {

	/**
	 * デフォルトコンストラクタです。
	 */
	public FileDatasetLoader() {}

	/**
	 * 価格データファイルローダーを保持します。
	 */
	private PriceDataLoader loader = new PriceDataLoader();

	/**
	 * 価格データファイルローダーを返します。
	 * 
	 * @return 価格データファイルローダー
	 */
	public PriceDataLoader getLoader() { return loader; }

	/**
	 * 価格データファイルローダーを設定します。
	 * 
	 * @param loader 価格データファイルローダー
	 */
	public void setLoader(final PriceDataLoader loader) { this.loader = loader; }

	/**
	 * シンボルとファイル名のマップを保持します。
	 */
	private Map<String, String> symbolMap = new HashMap<String, String>();

	/**
	 * シンボルとファイル名のマップを返します。
	 * 
	 * @return シンボルとファイル名のマップ
	 */
	public Map<String, String> getSymbolMap() { return symbolMap; }

	/**
	 * シンボルとファイル名のマップを設定します。
	 * 
	 * @param symbolMap シンボルとファイル名のマップ
	 */
	public void setSymbolMap(final Map<String, String> symbolMap) { this.symbolMap = symbolMap; }

	/**
	 * データの足の単位を保持します。
	 */
	private Interval interval = Interval.DAILY;

	/**
	 * データの足の単位を返します。
	 * 
	 * @return データの足の単位
	 */
	public Interval getInterval() { return interval; }

	/**
	 * データの足の単位を設定します。
	 * 
	 * @param interval データの足の単位
	 */
	public void setInterval(final Interval interval) { this.interval = interval; }

	/**
	 * DataLoadListener リスナーリストを保持します。
	 */
	private List<DatasetLoadListener> listeners = new ArrayList<DatasetLoadListener>(1);

	/**
	 * DatasetLoadListener をリスナーリストに追加します。
	 * 
	 * @param listener 追加する DatasetLoadListener
	 */
	public void addDatasetLoadListener(final DatasetLoadListener listener) {
		listeners.add(listener);
	}

	/**
	 * シンボルを保持します。
	 */
	private String symbol;

	@Override public void setSymbol(final String symbol) { this.symbol = symbol; }

	/**
	 * <p>データセットをロードして返します。</p>
	 * <p>データセットロードリスナーが登録されている場合は、リスナーの実装クラスへイベント通知も行います。</p>
	 * 
	 * @return データセット
	 * @throws LoadException データセットのロードに失敗した場合
	 */
	@Override
	public TimeSeriesDataset load() throws LoadException {
		final String filename = symbolMap.get(symbol);
		if (filename == null || filename.isEmpty())
			throw new LoadException("filename is empty.");
		try {
			final List<PriceData> prices = loader.load(filename);
			final TimeSeriesDataset dataset = new TimeSeriesDataset(interval, prices.toArray(new PriceData[]{}));
			dataset.setSymbol(symbol);

			final DatasetLoadEvent event = new DatasetLoadEvent(this, dataset);
			for (final DatasetLoadListener listener : listeners)
				listener.datasetLoaded(event);
			return dataset;
		} catch (Exception e) {
			throw new LoadException(e.getMessage(), e);
		}
	}

}
