/*
 * 作成日: 2005/10/27
 *
 * TODO この生成されたファイルのテンプレートを変更するには次へジャンプ:
 * ウィンドウ - 設定 - Java - コード・スタイル - コード・テンプレート
 */
package org.F11.scada.tool.logdata;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.F11.scada.data.ConvertValue;
import org.F11.scada.tool.io.LoggingDataStore;
import org.F11.scada.tool.io.StrategyUtility;
import org.F11.scada.tool.io.parser.Column;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MakeCsvDataLogic implements MakeCsvService {
	private final Log log = LogFactory.getLog(MakeCsvDataLogic.class);
	private final Connection con;
	private final DataConditionsForm dataCondForm;
	private final List<String> tables;

	/**
	 * @param dataCondForm
	 * 
	 */
	public MakeCsvDataLogic(
			Connection con,
			DataConditionsForm dataCondForm,
			List<String> tables) {
		super();
		this.con = con;
		this.dataCondForm = dataCondForm;
		this.tables = tables;
	}

	public List getHeaderData(DataConditionsForm form) {
		CsvCreatorUtil creator = new CsvCreatorUtil();
		return creator.getHeaderData(form, con);
	}

	public List getCsvData(DataConditionsForm form) {
		PreparedStatement st = null;
		try {
			String loggingName = form.getTableString();

			CsvCreatorUtil creator = new CsvCreatorUtil();
			List columns = creator.getColumns(loggingName);

			LoggingDataStore store = new LoggingDataStore();
			StrategyUtility util = new StrategyUtility(con);
			Map itemMap = store.getLoggingItemMap(util, columns);

			String sql = getSql(loggingName);
			st =
				con.prepareStatement(
					sql,
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_READ_ONLY);
			if (form.isStEneble()) {
				st.setTimestamp(1, creator.getStartTime(form));
			} else {
				st.setTimestamp(1, new Timestamp(0));
			}
			if (form.isEtEneble()) {
				st.setTimestamp(2, creator.getEndTime(form));
			} else {
				st.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
			}
			Collection dataList = store.getLoggingData(st, columns);
			st.close();
			return getCsvLoggingData(dataList, columns, itemMap);
		} catch (Exception e) {
			log.error("sql exeute error : ", e);
			return Collections.EMPTY_LIST;
		} catch (OutOfMemoryError e) {
			log.error("メモリ不足になったと思われます。もうすこし短い期間の日付指定を入力してください。");
			log.error("sql exeute error : ", e);
			throw e;
		} finally {
			if (st != null) {
				try {
					st.close();
				} catch (SQLException e) {
					st = null;
				}
			}
		}
	}

	private String getSql(String loggingName) {
		if (tables.isEmpty()) {
			StringBuffer sqlbuf = new StringBuffer();
			sqlbuf.append("SELECT * FROM ").append(loggingName);
			sqlbuf.append(" WHERE f_revision=0 AND ?<=f_date AND f_date<?");
			sqlbuf.append(" ORDER BY f_date");
			return sqlbuf.toString();
		} else {
			StringBuffer sqlbuf = new StringBuffer();
			String tableZero = tables.get(0);
			String dateStr = tableZero + ".f_date";
			sqlbuf.append("SELECT * FROM ").append(getTables());
			sqlbuf
				.append(" WHERE ")
				.append(tableZero)
				.append(".f_revision=0 AND ? <= ")
				.append(dateStr)
				.append(" AND ")
				.append(dateStr)
				.append(" < ?");
			sqlbuf.append(" ORDER BY ").append(dateStr);
			String string = sqlbuf.toString();
			log.info(string);
			return string;
		}
	}

	private String getTables() {
		if (tables.size() == 1) {
			return tables.get(0);
		} else {
			StringBuilder b = new StringBuilder();
			for (int i = 0, count = tables.size() - 1; i < count; i++) {
				if (i == 0) {
					b.append(tables.get(i)).append(" ");
				}
				b
					.append("LEFT JOIN ")
					.append(tables.get(i + 1))
					.append(" ON ")
					.append(tables.get(i))
					.append(".f_date = ")
					.append(tables.get(i + 1))
					.append(".f_date");
				if (i < (count - 1)) {
					b.append(" ");
				}
			}
			return b.toString();
		}
	}

	private List getCsvLoggingData(
			Collection dataList,
			Collection columns,
			Map itemMap) {
		ArrayList csvLines = new ArrayList();
		for (Iterator it = dataList.iterator(); it.hasNext();) {
			Map datas = (Map) it.next();
			StringBuffer sb = new StringBuffer();

			Timestamp datetime = (Timestamp) datas.get("f_date");
			DateFormat dateformater = getFormat();
			sb.append(dateformater.format(new Date(datetime.getTime())));

			for (Iterator it2 = columns.iterator(); it2.hasNext();) {
				Column col = (Column) it2.next();
				Double data = (Double) datas.get(col.getProviderHolder());
				PointItemConverter item =
					(PointItemConverter) itemMap.get(col.getProviderHolder());
				ConvertValue cv = item.getConvertValue();

				sb.append(",");
				sb.append(cv.convertStringValue(data.doubleValue()));
			}
			csvLines.add(sb.toString());
		}
		return csvLines;
	}

	private DateFormat getFormat() {
		return "goda".equals(dataCondForm.getHeadString())
			? new SimpleDateFormat("yyyy/MM/dd HH:mm")
			: new SimpleDateFormat("yyyy/MM/dd,HH:mm:ss");
	}

}