// DormantNodeListItem.cpp
// e.moon 3jun99

#include "DormantNodeListItem.h"

#include <Application.h>
#include <Resources.h>
#include <DataIO.h>
#include <MediaRoster.h>
#include <MediaAddOn.h>
#include <TranslationKit.h>

#include "debug_tools.h"
#include "array_delete.h"

__USE_CORTEX_NAMESPACE

// -------------------------------------------------------- //
// constants
// -------------------------------------------------------- //
const float				DormantNodeListItem::s_iconWidth = 16.0;
const float				DormantNodeListItem::s_iconHeight = 16.0;
const float				DormantNodeListItem::s_iconPadX = 2.0;
const float				DormantNodeListItem::s_iconPadTop = 4.0;
const float				DormantNodeListItem::s_iconPadBottom = 3.0;
const float				DormantNodeListItem::s_textPadX = 4.0;

const uint16 DormantNodeListItem::s_iconCount = 4;

const rgb_color DormantNodeListItem::s_iconBackColor = {255,255,255,255};

const rgb_color DormantNodeListItem::s_textBackEdgeColor =
	tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT);
const rgb_color DormantNodeListItem::s_textBackColor =
	tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT);
const rgb_color DormantNodeListItem::s_textColor = {0,0,0,255};

const rgb_color DormantNodeListItem::s_sel_textBackColor = {64,64,192,255};
const rgb_color DormantNodeListItem::s_sel_textColor = {255,255,255,255};

// -------------------------------------------------------- //
// ctor/dtor
// -------------------------------------------------------- //

DormantNodeListItem::~DormantNodeListItem() {}
DormantNodeListItem::DormantNodeListItem(
	const dormant_node_info& info) :
	m_info(info),
	m_pFont(0),
	m_icons(s_iconCount, 0) {
	
	initFlavorInfo();
}
	
	
// -------------------------------------------------------- //
// internal operations
// -------------------------------------------------------- //

// count flavors, init icons
void DormantNodeListItem::initFlavorInfo() {
	BMediaRoster* r = BMediaRoster::Roster();
	status_t err = r->GetDormantFlavorInfoFor(
		m_info, &m_flavorInfo);
	if(err < B_OK) {
		PRINT((
			"DormantNodeListItem::initFlavorInfo(): GetDormantFlavorInfoFor():\n%s\n",
			strerror(err)));
		return;
	}
	
	enum icon_index {
		AUDIO_PRODUCER,
		VIDEO_PRODUCER,
		AUDIO_CONSUMER,
		VIDEO_CONSUMER
	};

	// scan input flavors
	for(int32 n = 0; n < m_flavorInfo.in_format_count; n++) {
		if(const_cast<media_format&>(m_flavorInfo.in_formats[n]).IsAudio()) {
			if(!m_icons[AUDIO_CONSUMER])
				m_icons[AUDIO_CONSUMER] = GetIcon(AUDIO_CONSUMER_ICON);
		}
		if(const_cast<media_format&>(m_flavorInfo.in_formats[n]).IsVideo()) {
			if(!m_icons[VIDEO_CONSUMER])
				m_icons[VIDEO_CONSUMER] = GetIcon(VIDEO_CONSUMER_ICON);
		}		
	}

	// scan output flavors
	for(int32 n = 0; n < m_flavorInfo.out_format_count; n++) {
		if(const_cast<media_format&>(m_flavorInfo.out_formats[n]).IsAudio()) {
			if(!m_icons[AUDIO_PRODUCER])
				m_icons[AUDIO_PRODUCER] = GetIcon(AUDIO_PRODUCER_ICON);
		}
		if(const_cast<media_format&>(m_flavorInfo.out_formats[n]).IsVideo()) {
			if(!m_icons[VIDEO_PRODUCER])
				m_icons[VIDEO_PRODUCER] = GetIcon(VIDEO_PRODUCER_ICON);
		}
	}
}

// -------------------------------------------------------- //
// ListItem impl.
// -------------------------------------------------------- //

/*static*/
void DormantNodeListItem::DrawBackground(
	BView* pOwner, BRect frame) {

	// icon area
	BRect iconR = frame;
	iconR.right = iconR.left + s_iconPadX +
		s_iconCount*(s_iconWidth+s_iconPadX);
	pOwner->SetLowColor(s_iconBackColor);	
	pOwner->FillRect(iconR, B_SOLID_LOW);

	// boundary
	pOwner->SetHighColor(s_textColor);
	pOwner->SetLowColor(s_textBackEdgeColor);
	BRect inframe = iconR;
	inframe.InsetBy(1.0, 0.0);
	pOwner->StrokeLine(inframe.RightTop(), inframe.RightBottom(), B_SOLID_LOW);
		
	pOwner->SetLowColor(s_textBackColor);
	pOwner->StrokeLine(iconR.RightTop(), iconR.RightBottom(), B_SOLID_LOW);

	// text area
	BRect textFrame = frame;	
	textFrame.left = iconR.right + 1.0;
	pOwner->FillRect(textFrame, B_SOLID_LOW);
}

void DormantNodeListItem::DrawItem(
	BView* pOwner, BRect frame,	bool complete) {


	BRect iconR = frame;
	iconR.right = iconR.left + s_iconPadX +
		m_icons.size()*(s_iconWidth+s_iconPadX);
	
	// draw icons
	pOwner->SetLowColor(s_iconBackColor);	
	if(!IsSelected()) {
		// pre-fill icon background to erase old selection stuff		
		pOwner->FillRect(iconR, B_SOLID_LOW);
	}

	BPoint iconP(frame.left + s_iconPadX, frame.top + s_iconPadTop);
	for(
		int n = 0;
		n < m_icons.size();
		n++, iconP += BPoint(s_iconWidth+s_iconPadX, 0.0))
		if(m_icons[n]) 
			pOwner->DrawBitmap(m_icons[n], iconP);

	// prepare to draw text; draw frame, etc.
	BFont oldFont;
	pOwner->GetFont(&oldFont);
	BFont font(oldFont);

	if(IsSelected()) {
		font.SetFace(B_BOLD_FACE);
		pOwner->SetFont(&font);
		
		pOwner->SetHighColor(s_sel_textColor);
		pOwner->SetLowColor(s_sel_textBackColor);
		BRect inframe = iconR;
		inframe.left -= 2;
		pOwner->StrokeRect(inframe, B_SOLID_LOW);
		inframe.InsetBy(1.0, 1.0);
		pOwner->StrokeRect(inframe, B_SOLID_LOW);
		inframe.InsetBy(1.0, 1.0);

//		pOwner->StrokeLine(inframe.LeftTop(), inframe.LeftTop(), B_SOLID_LOW);
//		pOwner->StrokeLine(inframe.LeftBottom(), inframe.LeftBottom(), B_SOLID_LOW);

		pOwner->StrokeLine(inframe.RightTop(), inframe.RightTop(), B_SOLID_LOW);
		pOwner->StrokeLine(inframe.RightBottom(), inframe.RightBottom(), B_SOLID_LOW);
	}
	else {
		// draw boundary
		pOwner->SetHighColor(s_textColor);
		pOwner->SetLowColor(s_textBackEdgeColor);
		BRect inframe = iconR;
		inframe.InsetBy(1.0, 0.0);
		pOwner->StrokeLine(inframe.RightTop(), inframe.RightBottom(), B_SOLID_LOW);
		
		pOwner->SetLowColor(s_textBackColor);
		pOwner->StrokeLine(iconR.RightTop(), iconR.RightBottom(), B_SOLID_LOW);
	}

	BRect textFrame = frame;	
	textFrame.left = iconP.x;
//	if(complete)
	pOwner->FillRect(textFrame, B_SOLID_LOW);
	
	// draw text
	float textLeft = textFrame.left + s_textPadX;
	pOwner->DrawString(
		m_info.name,
		BPoint(textLeft, frame.bottom - (m_fontHeight.descent+s_iconPadBottom+1)));
		
	pOwner->SetFont(&oldFont);
}

void DormantNodeListItem::Update(
	BView* pOwner, const BFont* pFont) {
	_inherited::Update(pOwner, pFont);

	// update height
	float minHeight = s_iconHeight+s_iconPadTop+s_iconPadBottom;
	if(Height() < minHeight)
		SetHeight(minHeight);
	
	m_pFont = pFont;
	pFont->GetHeight(&m_fontHeight);
}

// -------------------------------------------------------- //
// static icon-management stuff
// -------------------------------------------------------- //

bool DormantNodeListItem::s_iconCacheLoaded = false;
DormantNodeListItem::icon_map DormantNodeListItem::s_iconCache;
BLocker DormantNodeListItem::s_iconCacheLock("DormantNodeListItem::s_iconCacheLock");

BBitmap* DormantNodeListItem::GetIcon(icon_id id) {
	if(!s_iconCacheLoaded)
		LoadIcons();
	
	icon_map::iterator it = s_iconCache.find(id);
	if(it == s_iconCache.end())
		return 0;
	return (*it).second;
}

void DormantNodeListItem::LoadIcons() {
	s_iconCacheLock.Lock();

	DoLoad(AUDIO_PRODUCER_ICON);	
	DoLoad(AUDIO_CONSUMER_ICON);	
	DoLoad(VIDEO_PRODUCER_ICON);	
	DoLoad(VIDEO_CONSUMER_ICON);	
	
	s_iconCacheLoaded = true;
	s_iconCacheLock.Unlock();
}

void DormantNodeListItem::DoLoad(icon_id id) {
	BResources* pRes = be_app->AppResources();
	ASSERT(pRes);

	// find the resource
	const char* pName;
	size_t length;
	if(!pRes->GetResourceInfo(B_RAW_TYPE, id, &pName, &length)) {
		PRINT((
			"DormantNodeListItem::DoLoad('%c%c%c%c'): not found.\n",
			(id>>24), (id>>16)&0xff, (id>>8)&0xff, id&0xff));
		return;
	}

/*	
	// load the resource
	char* buffer = new char[length];
	array_delete<char> _d(buffer);
	BMemoryIO bufferIO((const void*)buffer, length);

	
	BBitmap* pBitmap = BTranslationUtils::GetBitmap(&bufferIO);
*/
	BBitmap* pBitmap = BTranslationUtils::GetBitmap(B_RAW_TYPE, id);
	if(!pBitmap) {
		PRINT((
			"DormantNodeListItem::DoLoad('%c%c%c%c'): not a known bitmap type.\n",
			(id>>24), (id>>16)&0xff, (id>>8)&0xff, id&0xff));
		return;
	}
	
	s_iconCache[id] = pBitmap;
}



// END -- DormantNodeListItem.cpp --


