#include "Board.h"

// constructor
Board::Board(Platform *platform)
{
	_platform = platform;
}

// destructor
Board::~Board()
{
}

// parse board data contained in a Value object
bool Board::ParseJSON(Value const &json)
{
	_name = json["name"];
	
	return true;
}

// parse a map containing boards file in form ok key=value
bool Board::ParseBoardsFile(VectorMap<String, String> const &map)
{
	for(int i = 0; i < map.GetCount(); i++)
	{
		String key = map.GetKey(i);
		if(!key.StartsWith(_name + "."))
			continue;
		key = key.Mid(_name.GetCount() + 1);
		String value = map[i];
		
		// name field is the description
		if(key == "name")
		{
			_description = value;
			continue;
		}
		
		// check for menu fields
		if(key.StartsWith("menu."))
		{
			// menu field, strip menu word
			// nano.menu.cpu.atmega168=ATmega168
			// nano.menu.cpu.atmega168.bootloader.low_fuses=0xff
			// NAME.menu.MKEY.MVAL.KEY=VAL
			// NAME.menu.MKEY.MVAL=MVALDESK
			//
			key = key.Mid(5);
			
			// get the menu key (cpu on upper example)
			int dotPos = key.Find(".");
			if(dotPos < 0)
				continue;
			String menuKey = key.Left(dotPos);
			
			// build (or get) the menu item
			BoardMenuItem &menuItem = _menuItems.GetAdd(menuKey);
			
			// get menu option (atmega168 in upper example)
			key = key.Mid(dotPos + 1);
			dotPos = key.Find(".");
			
			// if dot is not found, we've the description of the option (not a key=value)
			if(dotPos < 0)
			{
				menuItem._descriptions.GetAdd(key) = value;
			}
			// it's a key=value
			else
			{
				String menuValue = key.Left(dotPos);
				key = key.Mid(dotPos + 1);
				
				// now we've the menuValue and the pair (key+value) for this item
				menuItem._values.GetAdd(menuValue).Add(key, value);
			}
		}
		else
		{
			// a normal key, store it
			_values.Add(key, value);
		}
	}
	
	return true;
}

// get/set selectable items
VectorMap<String, int> Board::GetSelectedMenuItems(void) const
{
	VectorMap<String, int> res;
	
	for(int iItem = 0; iItem < _menuItems.GetCount(); iItem++)
		res.Add(_menuItems.GetKey(iItem), _menuItems[iItem]._selectedItem);
	return res;
}

void Board::SetSelectedMenuItems(VectorMap<String, int> const &items)
{
	for(int iItem = 0; iItem < items.GetCount(); iItem++)
	{
		int i = _menuItems.Find(items.GetKey(iItem));
		if(i < 0)
			continue;
		int selected = items[iItem];
		if(selected < _menuItems[i]._descriptions.GetCount())
			_menuItems[i]._selectedItem = selected;
		else
			_menuItems[i]._selectedItem = 0;
	}
}

// merge board fixed values with menu selected ones
VectorMap<String, String>Board::GetMergedValues(void) const
{
	// deep copy values onto result
	VectorMap<String, String> res(_values, 1);
	
	// walk through menu items
	for(int iItem = 0; iItem < _menuItems.GetCount(); iItem++)
	{
		BoardMenuItem const &item = _menuItems[iItem];
		int sel = item._selectedItem;
		VectorMap<String, String> const &itemValues = item._values[sel];
		for(int iVal = 0; iVal < itemValues.GetCount(); iVal++)
			res.GetAdd(itemValues.GetKey(iVal)) = itemValues[iVal];
	}
	
	return res;
}
		
