#include "DisplayTracks.h"
#include "setup.h"
#if VDRVERSNUM >= 10332
#include <vdr/device.h>
#endif
#ifdef VIDEOSTATUS
#include "videostatus.h"
#endif
#include "symbols/audioleft.xpm"
#include "symbols/audioright.xpm"
#include "symbols/audiostereo.xpm"
#include "symbols/arrowdown.xpm"
#include "symbols/arrowup.xpm"

extern bool vdrosd;
// --- cSkinElchiDisplayTracks ---------------------------------------------
cBitmap cSkinElchiDisplayTracks::bmAudioLeft(audioleft_xpm);
cBitmap cSkinElchiDisplayTracks::bmAudioRight(audioright_xpm);
cBitmap cSkinElchiDisplayTracks::bmAudioStereo(audiostereo_xpm);
cBitmap cSkinElchiDisplayTracks::bmArrowDown(arrowdown_xpm);
cBitmap cSkinElchiDisplayTracks::bmArrowUp(arrowup_xpm);

cSkinElchiDisplayTracks::cSkinElchiDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) {
    noflush = true;
#ifdef VIDEOSTATUS
    VideoStatus.Update();
#endif
    message = changed = false;
    font = cFont::GetFont(fontOsd);
    smallfont = cFont::GetFont(fontSml);
    lh = font->Height();
    lhh = lh / 2;
    currentIndex = -1;
    index = -1;
    offset = 0;
    numTracks = NumTracks;
    int ItemsWidth = font->Width(Title);
    for (int i = 0; i < NumTracks; i++)
	ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
    ItemsWidth += 10;
    x0 = 0;
    x1 = x0 + lhh;
#ifdef VIDEOSTATUS
  if (SkinElchiSetup.videostatus)
    vdrosd = (VideoStatus.NTSC() == (SkinElchiSetup.videosystem == vsNTSC));
  else
#endif
    vdrosd = (cDevice::PrimaryDevice()->GetVideoSystem() == vsNTSC) == (SkinElchiSetup.videosystem == vsNTSC);
    x3 = x0 + (vdrosd ? Setup.OSDWidth : SkinElchiSetup.osdwidth);
    x2 = x3 - lhh;
    int d = x3 - x0;
    if (d > (ItemsWidth + lh)) {
	d = (d - ItemsWidth - lh) & ~0x07; // must be multiple of 8
	x2 -= d;
	x3 -= d;
	}
    y0 = 0;
    y1 = y0 + lh;
    y2 = y1 + lh;
    y3 = y2 + NumTracks * lh;
    y4 = y3 + lh;
    y5 = y4 + lh;
    if (y5 > (y0 + (vdrosd ? Setup.OSDHeight : SkinElchiSetup.osdheight))) { //all right ??? i think, must be change !
	y5 = y0 + (vdrosd ? Setup.OSDHeight : SkinElchiSetup.osdheight);
	y4 = y5 - lh;
	y3 = y4 - lh;
	}
    osd = cOsdProvider::NewOsd(vdrosd ? Setup.OSDLeft : SkinElchiSetup.osdleft, ((vdrosd ? Setup.OSDTop : SkinElchiSetup.osdtop) + (Setup.ChannelInfoPos ? 0 : ((vdrosd ? Setup.OSDHeight : SkinElchiSetup.osdheight) - y5))));
    tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 4 } };
    osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
    tColor tr = Theme.Color(Transparent);
    osd->DrawRectangle(x0, y0, x1 - 1, y1 - lhh - 1, tr);
    tColor mtb = Theme.Color(clrMenuTitleBg);
    osd->DrawEllipse(x0, y0, x1 - 1, y1 - lhh - 1, mtb, 2);
    osd->DrawRectangle(x0, y0 + lhh , x1 - 1, y1 - 1, mtb);
    osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, mtb);
    tColor mtf = Theme.Color(clrMenuTitleFg);
    osd->DrawText(x1, y0, Title, mtf, tr, smallfont, x2 - x1);
    osd->DrawRectangle(x2, y0, x3 - 1, y1 - lhh - 1, tr);
    osd->DrawEllipse(x2, y0, x3 - 1, y1 - lhh  - 1, mtb, 1);
    osd->DrawRectangle(x2, y0 + lhh , x3 - 1, y1 - 1, mtb);
    osd->DrawRectangle(x0, y4, x1 - 1, y5 - lhh - 1, mtb);
    osd->DrawRectangle(x0, y4 + lhh, x1 - 1, y5 - 1, tr);
    osd->DrawEllipse(x0, y4 + lhh , x1 - 1, y5 - 1, mtb, 3);
    osd->DrawRectangle(x1, y4, x2 - 1, y5 - 1, mtb);
    osd->DrawRectangle(x2, y4, x3 - 1, y5 - lhh - 1, mtb);
    osd->DrawRectangle(x2, y4 + lhh, x3 - 1, y5 - 1, tr);
    osd->DrawEllipse(x2, y4 + lhh , x3 - 1, y5 - 1, mtb, 4);
    tColor bg = Theme.Color(clrBackground);
    osd->DrawRectangle(x0, y1, x3 - 1, y2 - 1, bg);
    osd->DrawRectangle(x0, y3, x3 - 1, y4 - 1, bg);
    int MaxTracks = MaxItems();
    Clear();
    if (MaxTracks > (numTracks - offset))
    MaxTracks = numTracks - offset;
    for (int i = offset; i < offset + MaxTracks; i++)
	SetItem(Tracks[i], i, false);
    if (numTracks > (offset + MaxTracks))
	osd->DrawBitmap(x2, y3 + (y4 - y3 - bmArrowDown.Height()) / 2, bmArrowDown, Theme.Color(clrMenuItemSelectable), Theme.Color(clrBackground));
    MessageScroll.DestWidth = x2 - x1;
    MessageScroll.Font = font;
    MessageScroll.xOff = x1;
    MessageScroll.yOff = y3;
    MessageScroll.delay = 20;
    MessageScroll.intervall = 7;
    noflush = false;
    }

cSkinElchiDisplayTracks::~cSkinElchiDisplayTracks() {
    noflush = true;
    message = changed = false;
    delete osd;
    }

int cSkinElchiDisplayTracks::MaxItems(void) {
    return (y3 - y2) / lh;
    }

void cSkinElchiDisplayTracks::Clear(void) {
    changed = true;
    int MaxTracks = MaxItems();
    tColor bg = Theme.Color(clrBackground);
    tColor mis = Theme.Color(clrMenuItemSelectable);
    osd->DrawBitmap(x2, y1 + (y2 - y1 - bmArrowUp.Height()) / 2, bmArrowUp, (offset > 0) ? mis : bg, bg);
    osd->DrawBitmap(x2, y3 + (y4 - y3 - bmArrowDown.Height()) / 2, bmArrowDown, (numTracks > (offset + MaxTracks)) ? mis : bg, bg);
    osd->DrawRectangle(x0, y2, x3 - 1, y3 - 1, Theme.Color(clrBackground));
    }

void cSkinElchiDisplayTracks::SetItem(const char *Text, int Index, bool Current) {
    int y = y2 + Index * lh - offset * lh;
    tColor fg, bg;
    if (Current) {
	fg = Theme.Color(clrMenuItemCurrentFg);
	bg = Theme.Color(clrMenuItemCurrentBg);
	currentIndex = Index;
	}
    else {
	fg = Theme.Color(clrMenuItemSelectable);
	bg = Theme.Color(clrBackground);
	}
    osd->DrawText(x1, y, Text, fg, bg, font, x2 - x1);
    if (currentIndex == Index) {
	osd->DrawEllipse(x0, y, x0 + lhh - 1, y + lh - 1, bg, 7);
	osd->DrawEllipse(x3 - lhh, y, x3 - 1, y + lh - 1, bg, 5);
	}
    }

void cSkinElchiDisplayTracks::SetTrack(int Index, const char * const *Tracks) {
    changed = true;
    if (index != Index) {
	tColor bg = Theme.Color(clrBackground);
	osd->DrawRectangle(x0, y2, x1 - 1, y3 - 1, bg);
	osd->DrawRectangle(x2, y2, x3 - 1, y3 - 1, bg);
	if (currentIndex >= 0) {
	    int MaxTracks = MaxItems();
	    if ((Index - offset) >= MaxTracks) {
		offset += MaxTracks - 1;
  		Clear();
		if (MaxTracks > (numTracks - offset))
		    MaxTracks = numTracks - offset;
		for (int i = offset; i < offset + MaxTracks; i++)
    		    SetItem(Tracks[i], i, false);
		}
    	    else {
		if (Index < offset) {
	    	    offset -= MaxTracks - 1;
  		    Clear();
		    if (MaxTracks > (numTracks - offset))
			MaxTracks = numTracks - offset;
		    for (int i = offset; i < offset + MaxTracks; i++)
    			SetItem(Tracks[i], i, false);
    		    }
		else
		    SetItem(Tracks[currentIndex], currentIndex, false);
		}
	    }
	else {
    	    int MaxTracks = MaxItems();
    	    if ((Index + 1) > MaxTracks) {
		int temp = Index + 1;
    		while (temp > MaxTracks) {
		    offset += MaxTracks - 1;
		    temp   -= MaxTracks - 1;
		    }
  		Clear();
		if (MaxTracks > (numTracks - offset))
		    MaxTracks = numTracks - offset;
		for (int i = offset; i < offset + MaxTracks; i++)
    		    SetItem(Tracks[i], i, false);
		}
	    }
	SetItem(Tracks[Index], Index, true);
	index = Index;
	}
    }

void cSkinElchiDisplayTracks::SetAudioChannel(int AudioChannel) {
    changed = true;
    cBitmap *bm = NULL;
    switch (AudioChannel) {
	case 0: bm = &bmAudioStereo; break;
	case 1: bm = &bmAudioLeft;   break;
	case 2: bm = &bmAudioRight;  break;
	}
    if (bm)
	osd->DrawBitmap(x1, y4 + (y5 - y4 - bm->Height()) / 2, *bm, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg));
    else
	osd->DrawRectangle(x1, y4, x2 - 1, y5 - 1, Theme.Color(clrMenuTitleBg));
    }

void cSkinElchiDisplayTracks::SetMessage(eMessageType Type, const char *Text) {
#ifdef DEBUG
    isyslog("skinelchi: cSkinElchiDisplayTracks::SetMessage(%d,%s)", (int)Type, Text);
#endif
    if (Text) {
	char *text;
	asprintf(&text, "%s", Text);
	if (!strcasecmp(text, tr("Going to sleep in about one minute"))) {
	    asprintf(&text, "\"%s\" <- Sleeptimer-Message received -> not printed on screen", Text);
	    esyslog(text);
	    }
	else {
	    message = changed = true;
	    MessageScroll.Fg = Theme.Color(clrMessageStatusFg + 2 * Type);
	    MessageScroll.Bg = Theme.Color(clrMessageStatusBg + 2 * Type);
	    osd->DrawEllipse(x0, y3, x1 - 1, y4 - 1, MessageScroll.Bg, 7);
	    if (MessageScroll.SetText(Text)) {
		MessageScroll.pos = 0;
		MessageScroll.dir = -1;
		MessageScroll.Time.Set();
		osd->DrawText(MessageScroll.xOff, MessageScroll.yOff, MessageScroll.Text, MessageScroll.Fg, MessageScroll.Bg, MessageScroll.Font, MessageScroll.DestWidth);
		}
	     else {
		MessageScroll.dir = 0;
		osd->DrawText(MessageScroll.xOff, MessageScroll.yOff, MessageScroll.Text, MessageScroll.Fg, MessageScroll.Bg, MessageScroll.Font, MessageScroll.DestWidth, taCenter);
		}
	    osd->DrawEllipse(x2, y3, x3 - 1, y4 - 1, MessageScroll.Bg, 5);
	    }
	free(text);
	}
    else {
	if (message) {
	    changed = true;
	    MessageScroll.dir = 0;
	    message = false;
	    osd->DrawRectangle(x0, y3, x3 - 1, y4 - 1, Theme.Color(clrBackground));
	    }
	}
    }

void cSkinElchiDisplayTracks::Flush(void) {
    if (!noflush) {
	noflush = true;
	if (changed) {
#ifdef DEBUG
	    isyslog("skinelchi: cSkinElchiDisplayTracks::(Flush)");
#endif
	    osd->Flush();
	    changed = false;
	    }
	else {
	    if (MessageScroll.dir) {//for scrolling
		if (MessageScroll.DrawNeeded()) {
#ifdef DEBUG
	    	    isyslog("skinelchi: cSkinElchiDisplayTracks::(Flush) because message is show");
#endif
		    for (int i = 0; i < MessageScroll.DestWidth; i++) {
			for (int j = 0; j < MessageScroll.Height(); j++)
		    	    osd->DrawPixel(MessageScroll.xOff + i, MessageScroll.yOff + j, MessageScroll.bmp->Color(*(MessageScroll.bmp->Data(i + MessageScroll.pos, j))));
			}
		    osd->Flush();
		    }
		}
#ifdef DEBUG
	    else
		isyslog("skinelchi: skip cSkinElchiDisplayTracks::Flush()");
#endif
	    }
	noflush = false;
	}
#ifdef DEBUG
	else
    	    isyslog("skinelchi: skip cSkinElchiDisplayTracks::Flush() because cSkinElchiDisplayTracks::Flush() is active");
#endif
    }

