/*
 * Created on Sep 17, 2008 (C) Copyright TANDBERG Television Ltd.
 */

package com.tandbergtv.workflow.web.table;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Vijay Silva
 */
public class TableExtensionBuilder {

	/* The column attribute for table extension key (indicating the column is a table extension) */
	private static final String TABLE_EXTENSION_ATTRIBUTE = "TableExtensionKey";

	/* The column attribute for table extension loader implementation */
	private static final String TABLE_EXTENSION_LOADER_IMPL_ATTRIBUTE = "TableExtensionLoaderImpl";

	/**
	 * Build all the Table Extensions defined in the current table.
	 * 
	 * @param table The Table in which to replace all extensions
	 * @param runtimeProperties The runtime properties to help determine the extended columns.
	 */
	public void buildTable(Table table, Map<String, String> runtimeProperties) {
		if (table == null)
			return;

		/* Ensure that the runtime properties map is never null */
		if (runtimeProperties == null)
			runtimeProperties = new HashMap<String, String>();

		/* Replace all extension columns */
		String tableName = table.getId();
		List<Column> replacedColumns = new ArrayList<Column>();
		for (Column column : table.getColumns()) {
			String key = column.getColumnAttribute(TABLE_EXTENSION_ATTRIBUTE);
			if (key != null) {
				ITableExtensionLoader loader = this.getExtensionLoader(column, tableName, key);
				List<Column> extendedColumns = loader.loadExtension(key, runtimeProperties);
				if (extendedColumns != null) {
					this.updateColumnWidths(column, extendedColumns);
					replacedColumns.addAll(extendedColumns);
				}
			} else {
				replacedColumns.add(column);
			}
		}

		table.setColumns(replacedColumns);
	}

	/* Create an instance of the Table Extension Loader implementation */
	private ITableExtensionLoader getExtensionLoader(Column column, String tableName,
			String extensionKey) {
		String extensionImpl = column.getColumnAttribute(TABLE_EXTENSION_LOADER_IMPL_ATTRIBUTE);
		try {
			Class<?> clazz = Class.forName(extensionImpl);
			Object instance = clazz.newInstance();
			return ITableExtensionLoader.class.cast(instance);
		} catch (Exception e) {
			String msg = "Failed to load ITableExtensionLoader implementation: " + extensionImpl
					+ " when building table[" + tableName + ", " + extensionKey + "].";
			throw new RuntimeException(msg, e);
		}
	}

	/* Update the column widths specified (if specified as percentages) */
	private void updateColumnWidths(Column extensionColumn, List<Column> extendedColumns) {
		String widthValue = extensionColumn.getWidth();
		if (widthValue == null)
			widthValue = "";

		double width = 1;
		NumberFormat format = NumberFormat.getPercentInstance();
		format.setMaximumFractionDigits(0);
		try {
			width = format.parse(widthValue.trim()).doubleValue();
		} catch (Exception e) {
			/* Assume the width is 100% */
		}

		for (Column column : extendedColumns) {
			String columnWidthValue = column.getColumnAttribute("Width");
			if (columnWidthValue != null) {
				try {
					double columnWidth = format.parse(columnWidthValue.trim()).doubleValue();
					columnWidth = Math.floor(columnWidth * width * 100D)/100D;
					column.setColumnAttribute("Width", format.format(columnWidth));
				} catch (Exception e) {
					/* Ignore assigning width to this column */
				}
			}
		}
	}
}
