package de.lcag.common;

import java.io.IOException;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import javax.management.OperationsException;

import routines.LcagDateTime;

public class HashTable extends AbstractTable {

	public static final String DEFAULT_TABLE_NAME = "Unnamed Table";

	private String name = DEFAULT_TABLE_NAME;

	public HashTable() {
		super();
		this.setDefaultDateFormat(LcagDateTime.DATETIME_FORMAT_ISO8601_UTC);
	}

	public HashTable(String... aColumnNameList) {
		this();

		this.addColumns(aColumnNameList);
	}

	/**
	 * Take over structure (column names) but no data from another table
	 * 
	 * @param pSrcTable
	 */
	public HashTable(AbstractTable pSrcTable) {
		super();
		this.defaultValue = pSrcTable.defaultValue;
		this.defaultString = pSrcTable.defaultString;
		this.defaultDateFormat = pSrcTable.defaultDateFormat;

		Set<String> columnNames = pSrcTable.getColumnNames();
		this.addColumns(columnNames);
	}

	public HashTable(Object pDefaultValue, SimpleDateFormat pDefaultDateFormat) {
		super();
		this.defaultValue = pDefaultValue;
		this.defaultString = String.valueOf((String) defaultValue); // results in default java "null"

		this.setDefaultDateFormat(pDefaultDateFormat);
	}

	public HashTable(Map<String, Object> pParams) {
		super();
		SimpleDateFormat defaultDateFormat = (SimpleDateFormat) pParams.getOrDefault("DateFormat",
				LcagDateTime.DATETIME_FORMAT_ISO8601_UTC);
		Object defaultValue = pParams.get("DefaultValue");

		this.setDefaultDateFormat(defaultDateFormat);
		this.setDefaultValue(defaultValue);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		if (name != null) {
			this.name = name;
		}
	}

	public void setCellValue(int row, int colNo, Object v) {
		try {
			Collection<String> colNames = this.getColumnLabels();
			Object[] colNameList = colNames.toArray();

			String colName = (String) colNameList[colNo];

			this.setCellValue(row, colName, v);
		} catch (IndexOutOfBoundsException e) {
			int n = this.getColumnNames().size();

			if (v == null || "".equals(v.toString().trim())) {
				log.warn(
						"setCellValue(row %d, col %d): Column number %d does not exist (max is %d) => ignored setting to empty or null value",
						row, colNo, colNo, n - 1);
			} else {
				String msg = String.format(
						"setCellValue(row %d, col %d): Column number %d does not exist (max is %d) => exception as cannot set to value '%s'",
						row, colNo, colNo, n - 1, v.toString());
				throw new IndexOutOfBoundsException(msg);
			}

		}
	}

	public void register() throws OperationsException {
		Table.register(name, this);
	}

	@Override
	public void integrateDiff(TableComparisonResult pDiff) throws IOException {
		// TODO Auto-generated method stub

	}

	@Override
	public Path getFilePath() {
		// TODO Auto-generated method stub
		return null;
	}

	public void addRow(Object... values) {
		int rowNo = this.newRow();
		int colNo = 0;

		for (Object value : values) {
			this.setCellValue(rowNo, colNo++, value);
		}
	}
}
