#include "Fortschritt.h"
#include "Rahmen.h"
#include "Farbe.h"
#include "Bild.h"
#include "Schrift.h"
#include "Punkt.h"
#include "Text.h"

using namespace Framework;

// Inhalt der FBalken Klasse aus Fortschritt.h 
// Konstruktor 
FBalken::FBalken()
{
	maxAk = 0;
	ak = 0;
	rahmen = 0;
	fRahmen = 0;
	bgF = 0;
	fBgF = 0;
	bgBild = 0;
	fBgBild = 0;
	schrift = 0;
	schriftFarbe = 0;
	style = 0;
	ref = 1;
}

// Destructor 
FBalken::~FBalken()
{
	if( rahmen )
		rahmen->release();
	if( fRahmen )
		fRahmen->release();
	if( bgF )
		bgF->release();
	if( fBgF )
		fBgF->release();
	if( bgBild )
		bgBild->release();
	if( fBgBild )
		fBgBild->release();
	if( schrift )
		schrift->release();
	if( schriftFarbe )
		schriftFarbe->release();
}

// nicht constant 
void FBalken::setAktionAnzahl( __int64 ak ) // setzt die anzahl der Aktionen
{
	maxAk = ak;
}

void FBalken::aktionPlus() // eine Aktion ist fertig
{
	ak++;
	if( ak > maxAk )
		ak = maxAk;
}

void FBalken::aktionPlus( __int64 aktionen ) // mehrere Aktionen sind fertig
{
	ak += aktionen;
	if( ak > maxAk )
		ak = maxAk;
}

void FBalken::reset() // setzt die fertigen Aktionen zurück
{
	ak = 0;
}

void FBalken::setRahmenZ( LRahmen *ram ) // setzt einen Zeiger zum Rahmen
{
	if( rahmen )
		rahmen->release();
	rahmen = ram;
}

void FBalken::setRFarbeZ( Farbe *f ) // setzt die Rahmen Farbe
{
	if( !rahmen )
		rahmen = new LRahmen();
	rahmen->setFarbeZ( f );
}

void FBalken::setRFarbe( int fc )
{
	if( !rahmen )
		rahmen = new LRahmen();
	rahmen->setFarbe( fc );
}

void FBalken::setRFarbe( Farbe *f )
{
	if( !rahmen )
		rahmen = new LRahmen();
	rahmen->setFarbe( f );
}

void FBalken::setRBreite( int br ) // setzt die Rahmen Breite
{
	if( !rahmen )
		rahmen = new LRahmen();
	rahmen->setRamenBreite( br );
}

void FBalken::setFRahmenZ( LRahmen *ram ) // setzt einen Zeiger zum Fertig Rahmen
{
	if( fRahmen )
		fRahmen->release();
	fRahmen = ram;
}

void FBalken::setFRFarbeZ( Farbe *f ) // setzt die Fertig Rahmen Farbe
{
	if( !fRahmen )
		fRahmen = new LRahmen();
	fRahmen->setFarbeZ( f );
}

void FBalken::setFRFarbe( int fc )
{
	if( !fRahmen )
		fRahmen = new LRahmen();
	fRahmen->setFarbe( fc );
}

void FBalken::setFRFarbe( Farbe *f )
{
	if( !fRahmen )
		fRahmen = new LRahmen();
	fRahmen->setFarbe( f );
}

void FBalken::setFRBreite( int br ) // setzt die Fertig Rahmen Breite
{
	if( !fRahmen )
		fRahmen = new LRahmen();
	fRahmen->setRamenBreite( br );
}

void FBalken::setBgFarbeZ( Farbe *f ) // setzt einen Zeiger zur Hintergrund Farbe
{
	if( bgF )
		bgF->release();
	bgF = f;
}

void FBalken::setBgFarbe( int fc )
{
	if( !bgF )
		bgF = new Farbe();
	bgF->setFarbe( fc );
}

void FBalken::setBgFarbe( Farbe *f )
{
	if( !bgF )
		bgF = new Farbe();
	bgF->setFarbe( f->getFarbe() );
	f->release();
}

void FBalken::setFBgFarbeZ( Farbe *f ) // setzt einen Zeiger zur Fertig Hintergrund Farbe
{
	if( fBgF )
		fBgF->release();
	fBgF = f;
}

void FBalken::setFBgFarbe( int fc )
{
	if( !fBgF )
		fBgF = new Farbe();
	fBgF->setFarbe( fc );
}

void FBalken::setFBgFarbe( Farbe *f )
{
	if( !fBgF )
		fBgF = new Farbe();
	fBgF->setFarbe( f->getFarbe() );
	f->release();
}

void FBalken::setBgBildZ( Bild *b ) // setzt das Hintergrund Bild
{
	if( bgBild )
		bgBild->release();
	bgBild = b;
}

void FBalken::setBgBild( Bild *b ) // kopiert in das Hintergrund Bild
{
	if( !bgBild )
		bgBild = new Bild();
	bgBild->neuBild( b->getGröße(), new Farbe() );
	bgBild->drawBild( 0, 0, b->getBreite(), b->getHöhe(), b );
	b->release();
}

void FBalken::setFBgBildZ( Bild *b ) // setzt das Fertig Hintergrund Bild
{
	if( fBgBild )
		fBgBild->release();
	fBgBild = b;
}

void FBalken::setFBgBild( Bild *b ) // kopiert in das Fertig Hintergrund Bild
{
	if( !fBgBild )
		fBgBild = new Bild();
	fBgBild->neuBild( b->getGröße(), new Farbe() );
	fBgBild->drawBild( 0, 0, b->getBreite(), b->getHöhe(), b );
	b->release();
}

void FBalken::setSchriftZ( Schrift *s ) // setzt die Schrift
{
	if( schrift )
		schrift->release();
	schrift = s;
}

void FBalken::setSFarbeZ( Farbe * f ) // setzt die Schrift Farbe
{
	if( schriftFarbe )
		schriftFarbe->release();
	schriftFarbe = f;
}

void FBalken::setSFarbe( int fc )
{
	if( !schriftFarbe )
		schriftFarbe = new Farbe();
	schriftFarbe->setFarbe( fc );
}

void FBalken::setSFarbe( Farbe *f )
{
	if( !schriftFarbe )
		schriftFarbe = new Farbe();
	schriftFarbe->setFarbe( f->getFarbe() );
	f->release();
}

void FBalken::setSGröße( unsigned char gr ) // setzt die Schrift größe
{
	schriftGröße = gr;
}

void FBalken::addStyle( int style ) // setzt den Style
{
	this->style |= style;
}

void FBalken::setStyle( int style )
{
	this->style = style;
}

void FBalken::setStyle( int style, bool add_remove )
{
	if( add_remove )
		this->style |= style;
	else
		this->style &= ~style;
}

void FBalken::löscheStyle( int style )
{
	this->style &= ~style;
}

void FBalken::render( Bild *zrObj ) // zeichnet nach zrObj
{
	if( !hatStyle( FB_Style::Sichtbar ) )
		return;
	lockObjekt();
	zrObj->setDrawOptions( pos->x, pos->y, pos->x + gr->x, pos->y + gr->y );
	int rbr = 0;
	if( hatStyle( FB_Style::Rahmen ) && rahmen )
	{
		rahmen->setPosition( pos->x, pos->y );
		rahmen->setGröße( gr->x, gr->y );
		rahmen->render( zrObj );
		rbr = rahmen->getRBreite();
	}
	if( hatStyle( FB_Style::Hintergrund ) )
	{
		if( bgF )
		{
			if( hatStyle( FB_Style::HAlpha ) )
				zrObj->alphaRegion( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgF->getFarbe() );
			else
				zrObj->füllRegion( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgF->getFarbe() );
		}
		if( hatStyle( FB_Style::HBild ) && bgBild )
		{
			if( hatStyle( FB_Style::HAlpha ) )
				zrObj->alphaBild( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgBild );
			else
				zrObj->drawBild( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgBild );
		}
	}
	int xx = pos->x;
	int yy = pos->y;
	int hö = 0;
	int br = 0;
	if( hatStyle( FB_Style::L_R ) )
	{
		hö = gr->y;
		br = (int)( ( gr->x / 100.0 ) * getProzent() );
	}
	else if( hatStyle( FB_Style::R_L ) )
	{
		hö = gr->y;
		br = (int)( ( gr->x / 100.0 ) * getProzent() );
		xx += (int)( gr->x - ( gr->x / 100.0 ) * getProzent() );
	}
	else if( hatStyle( FB_Style::O_U ) )
	{
		hö = (int)( ( gr->y / 100.0 ) * getProzent() );
		br = gr->x;
	}
	else if( hatStyle( FB_Style::U_O ) )
	{
		hö = (int)( ( gr->y / 100.0 ) * getProzent() );
		br = gr->x;
		yy += (int)( gr->y - ( gr->y / 100.0 ) * getProzent() );
	}
	if( maxAk == 0 )
		hö = 0, br = 0;
	zrObj->setDrawOptions( xx, yy, xx + br, yy + hö );
	if( hatStyle( FB_Style::FRahmen ) && fRahmen )
	{
		fRahmen->setPosition( pos->x, pos->y );
		fRahmen->setGröße( gr->x, gr->y );
		fRahmen->render( zrObj );
		rbr = fRahmen->getRBreite();
	}
	if( hatStyle( FB_Style::FFarbe ) && fBgF )
	{
		if( hatStyle( FB_Style::FAlpha ) )
			zrObj->alphaRegion( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgF->getFarbe() );
		else
			zrObj->füllRegion( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgF->getFarbe() );
	}
	if( hatStyle( FB_Style::FBild ) && fBgBild )
	{
		if( hatStyle( FB_Style::HAlpha ) )
			zrObj->alphaBild( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgBild );
		else
			zrObj->drawBild( pos->x + rbr, pos->y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgBild );
	}
	zrObj->setDrawOptions( -1, -1, -1, -1 );
	if( hatStyle( FB_Style::Prozent ) && schrift && schriftFarbe )
	{
		schrift->lockSchrift();
		schrift->setSchriftGröße( schriftGröße );
		schrift->setFarbe( schriftFarbe->getFarbe() );
		Text *txt = new Text( "" );
		txt->anhängen( (int)getProzent() );
		txt->anhängen( "%" );
		schrift->setDrawPosition( pos->x + rbr + ( gr->x - rbr * 2 ) / 2 - schrift->getTextBreite( txt->getThis() ) / 2, pos->y + rbr + ( gr->y - rbr * 2 ) / 2 - schrift->getTextHöhe( txt->getThis() ) / 2 );
		schrift->renderText( txt, zrObj );
		schrift->unlockSchrift();
	}
	zrObj->setDrawOptions( -1, -1, -1, -1 );
	unlockObjekt();
}

void FBalken::render( int xOff, int yOff, int bOff, int hOff, Bild *zrObj )
{
	if( !hatStyle( FB_Style::Sichtbar ) )
		return;
	lockObjekt();
	int x = pos->x, y = pos->y, b = gr->x, h = gr->y;
	x += xOff;
	y += yOff;
	int xx = x < ( xOff + bOff ) ? x : ( xOff + bOff );
	xx = xx >= xOff ? xx : xOff;
	int yy = y < ( yOff + hOff ) ? y : ( yOff + hOff );
	yy = yy >= yOff ? yy : yOff;
	int xb = ( x + b ) < ( xOff + bOff ) ? ( x + b ) : ( xOff + bOff );
	xb = xb >= xOff ? xb : ( xOff - 1 );
	int yh = ( y + h ) < ( yOff + hOff ) ? ( y + h ) : ( yOff + hOff );
	yh = yh >= yOff ? yh : ( yOff - 1 );
	if( xx == xOff + bOff || yy == yOff + hOff || xb == xOff - 1 || yh == yOff - 1 )
	{
		unlockObjekt();
		return;
	}
	zrObj->setDrawOptions( xx, yy, xb, yh );
	int rbr = 0;
	if( hatStyle( FB_Style::Rahmen ) && rahmen )
	{
		rahmen->setPosition( x, y );
		rahmen->setGröße( gr->x, gr->y );
		rahmen->render( zrObj );
		rbr = rahmen->getRBreite();
	}
	if( hatStyle( FB_Style::Hintergrund ) )
	{
		if( bgF )
		{
			if( hatStyle( FB_Style::HAlpha ) )
				zrObj->alphaRegion( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgF->getFarbe() );
			else
				zrObj->füllRegion( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgF->getFarbe() );
		}
		if( hatStyle( FB_Style::HBild ) && bgBild )
		{
			if( hatStyle( FB_Style::HAlpha ) )
				zrObj->alphaBild( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgBild );
			else
				zrObj->drawBild( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, bgBild );
		}
	}
	b = 0, h = 0;
	if( hatStyle( FB_Style::L_R ) )
	{
		h = gr->y;
		b = (int)( ( gr->x / 100.0 ) * getProzent() );
	}
	else if( hatStyle( FB_Style::R_L ) )
	{
		h = gr->y;
		b = (int)( ( gr->x / 100.0 ) * getProzent() );
		xx = pos->x + (int)( gr->x - ( gr->x / 100.0 ) * getProzent() );
	}
	else if( hatStyle( FB_Style::O_U ) )
	{
		h = (int)( ( gr->y / 100.0 ) * getProzent() );
		b = gr->x;
	}
	else if( hatStyle( FB_Style::U_O ) )
	{
		h = (int)( ( gr->y / 100.0 ) * getProzent() );
		b = gr->x;
		yy = pos->y + (int)( gr->y - ( gr->y / 100.0 ) * getProzent() );
	}
	if( maxAk == 0 )
		h = 0, b = 0;
	x += xOff;
	y += yOff;
	xx = x < ( xOff + bOff ) ? x : ( xOff + bOff );
	xx = xx >= xOff ? xx : xOff;
	yy = y < ( yOff + hOff ) ? y : ( yOff + hOff );
	yy = yy >= yOff ? yy : yOff;
	xb = ( x + b ) < ( xOff + bOff ) ? ( x + b ) : ( xOff + bOff );
	xb = xb >= xOff ? xb : ( xOff - 1 );
	yh = ( y + h ) < ( yOff + hOff ) ? ( y + h ) : ( yOff + hOff );
	yh = yh >= yOff ? yh : ( yOff - 1 );
	if( xx == xOff + bOff || yy == yOff + hOff || xb == xOff - 1 || yh == yOff - 1 )
	{
		unlockObjekt();
		zrObj->setDrawOptions( -1, -1, -1, -1 );
		return;
	}
	zrObj->setDrawOptions( xx, yy, xb, yh );
	if( hatStyle( FB_Style::FRahmen ) && fRahmen )
	{
		fRahmen->setPosition( x, y );
		fRahmen->setGröße( gr->x, gr->y );
		fRahmen->render( zrObj );
		rbr = fRahmen->getRBreite();
	}
	if( hatStyle( FB_Style::FFarbe ) && fBgF )
	{
		if( hatStyle( FB_Style::FAlpha ) )
			zrObj->alphaRegion( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgF->getFarbe() );
		else
			zrObj->füllRegion( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgF->getFarbe() );
	}
	if( hatStyle( FB_Style::FBild ) && fBgBild )
	{
		if( hatStyle( FB_Style::HAlpha ) )
			zrObj->alphaBild( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgBild );
		else
			zrObj->drawBild( x + rbr, y + rbr, gr->x - rbr * 2, gr->y - rbr * 2, fBgBild );
	}
	zrObj->setDrawOptions( -1, -1, -1, -1 );
	if( hatStyle( FB_Style::Prozent ) && schrift && schriftFarbe )
	{
		schrift->lockSchrift();
		schrift->setSchriftGröße( schriftGröße );
		schrift->setFarbe( schriftFarbe->getFarbe() );
		Text *txt = new Text( "" );
		txt->anhängen( (int)getProzent() );
		txt->anhängen( "%" );
		schrift->setDrawPosition( x + rbr + ( gr->x - rbr * 2 ) / 2 - schrift->getTextBreite( txt->getThis() ) / 2, y + rbr + ( gr->y - rbr * 2 ) / 2 - schrift->getTextHöhe( txt->getThis() ) / 2 );
		schrift->renderText( txt, zrObj );
		schrift->unlockSchrift();
	}
	zrObj->setDrawOptions( -1, -1, -1, -1 );
	unlockObjekt();
}

// constant 
__int64 FBalken::getAktionAnzahl() const // gibt die Anzahl der Aktionen zurück
{
	return maxAk;
}

double FBalken::getProzent() const // gibt die momentane Prozentzahl zurück
{
	if( !maxAk )
		return 0;
	return ak / ( maxAk / 100.0 );
}

__int64 FBalken::getAktion() const // gibt die fertigen Aktionen zurück
{
	return ak;
}

LRahmen *FBalken::getRahmen() const // gibt den Rahmen zurück
{
	if( rahmen )
		return rahmen->getThis();
	return 0;
}

LRahmen *FBalken::zRahmen() const
{
	return rahmen;
}

LRahmen *FBalken::getFRahmen() const // gibt den Fertig Rahmen zurück
{
	if( fRahmen )
		return fRahmen->getThis();
	return 0;
}

LRahmen *FBalken::zFRahmen() const
{
	return fRahmen;
}

Farbe *FBalken::getBgFarbe() const // gibt die Hintergrund Farbe zurück
{
	if( bgF )
		return bgF->getThis();
	return 0;
}

Farbe *FBalken::zBgFarbe() const
{
	return bgF;
}

Farbe *FBalken::getFBgFarbe() const // gibt die Fertig Hintergrund Farbe zurück
{
	if( fBgF )
		return fBgF->getThis();
	return 0;
}

Farbe *FBalken::zFBgFarbe() const
{
	return fBgF;
}

Bild *FBalken::getBgBild() const // gibt das Hintergrund Bild zurück
{
	if( bgBild )
		return bgBild->getThis();
	return 0;
}

Bild *FBalken::zBgBild() const
{
	return bgBild;
}

Bild *FBalken::getFBgBild() const // gibt das Fertig Hintergrund Bild zurück
{
	if( fBgBild )
		return fBgBild->getThis();
	return 0;
}

Bild *FBalken::zFBgBild() const
{
	return fBgBild;
}

Schrift *FBalken::getSchrift() const // gibt die Schrift zurück
{
	if( schrift )
		return schrift->getThis();
	return 0;
}

Schrift *FBalken::zSchrift() const
{
	return schrift;
}

Farbe *FBalken::getSFarbe() const // gibt die Schrift Farbe zurück
{
	if( schriftFarbe )
		return schriftFarbe->getThis();
	return 0;
}

Farbe *FBalken::zSFarbe() const
{
	return schriftFarbe;
}

bool FBalken::hatStyle( int style ) const // prüft, ob style vorhanden
{
	return ( this->style | style ) == this->style;
}

bool FBalken::hatStyleNicht( int style ) const // prüft, ob style nicht vorhanden
{
	return ( this->style |style ) != this->style;
}

// Reference Counting 
FBalken *FBalken::getThis()
{
	ref++;
	return this;
}

FBalken *FBalken::release()
{
	ref--;
	if( ref == 0 )
		delete this;
	return 0;
}