#include "Knopf.h"

#include "AlphaFeld.h"
#include "Bild.h"
#include "Datei.h"
#include "DateiSystem.h"
#include "Globals.h"
#include "MausEreignis.h"
#include "Rahmen.h"
#include "Schrift.h"
#include "Scroll.h"
#include "TastaturEreignis.h"
#include "Text.h"
#include "ToolTip.h"

using namespace Framework;

// Inhalt der Knopf Klasse aus Knopf.h
// Konstruktor
Knopf::Knopf()
    : TextFeld(),
      klickFarbe(0xFF000000),
      klickBild(0),
      klickBuffer(0),
      klickIndex(0)
{
    style
        = Style::Erlaubt | Style::Buffered | Style::KlickBuffer | Style::Rahmen;
    this->setMausEreignis(_ret1ME);
    setSchriftFarbe(0xFFFFFFFF);
    setSchriftSize(12);
    setRahmenBreite(2);
    setRahmenFarbe(0xFF00FF00);
    setAlphaFeldFarbe(0x5500FF00);
    setAlphaFeldStrength(-5);
    setKBFarbe(0xFF000000);
    setKBStrength(20);
    addStyle(TextFeld::Style::Center);
}

// Destruktor
Knopf::~Knopf()
{
    if (klickBuffer) klickBuffer->release();
    if (klickBild) klickBild->release();
}

void Knopf::doMausEreignis(MausEreignis& me, bool userRet) // Maus Ereignis
{
    if (hatStyleNicht(Style::Erlaubt) || !userRet) return;
    if (me.id == ME_Betritt)
    {
        klickIndex = MausStand[M_Links];
        if (klickIndex) rend = 1;
    }
    if (me.id == ME_RLinks || me.id == ME_Leaves)
    {
        if (klickIndex) rend = 1;
        klickIndex = 0;
    }
    if (!me.verarbeitet)
    {
        if (me.id == ME_PLinks)
        {
            klickIndex = 1;
            rend = 1;
        }
        me.verarbeitet = 1;
    }
}

// nicht constant
void Knopf::setKlickFarbe(int fc) // setzt die Klick Farbe
{
    klickFarbe = fc;
    rend = 1;
}

void Knopf::setKlickBild(Bild* bild) // setzt das Klick Bild
{
    if (bild)
    {
        if (!klickBild) klickBild = new Bild();
        klickBild->neuBild(bild->getBreite(), bild->getHeight(), 0);
        int* buff1 = klickBild->getBuffer();
        int* buff2 = bild->getBuffer();
        for (int i = 0; i < bild->getBreite() * bild->getHeight(); ++i)
            buff1[i] = buff2[i];
        bild->release();
        rend = 1;
    }
}

void Knopf::setKlickBildZ(Bild* bild) // setzt einen Zeiger zum Klick Bild
{
    if (klickBild) klickBild->release();
    klickBild = bild;
    rend = 1;
}

void Knopf::setKBZ(AlphaFeld* af)
{
    if (klickBuffer) klickBuffer->release();
    klickBuffer = af;
    rend = 1;
}

void Knopf::setKBStrength(int st) // setzt die Stärke des Klick Buffers
{
    if (!klickBuffer) klickBuffer = new AlphaFeld();
    klickBuffer->setStrength(st);
    rend = 1;
}

void Knopf::setKBFarbe(int fc) // setzt die Farbe des Klick Buffers
{
    if (!klickBuffer) klickBuffer = new AlphaFeld();
    klickBuffer->setFarbe(fc);
    rend = 1;
}

// Verarbeitet Maus Nachrichten
//  te: Das Ereignis, was durch die Tastatur Eingabe ausgelößt wurde
void Knopf::doTastaturEreignis(TastaturEreignis& te) {}

void Knopf::render(Bild& zRObj) // zeichenet nach zRObj
{
    if (!hatStyle(Style::Sichtbar)) return;
    addStyle(TextFeld::Style::Center);
    bool erlaubt = hatStyle(Style::Erlaubt);
    bool rA = 0;
    if (!hatStyle(Style::Erlaubt))
    {
        zRObj.setAlpha(0x20);
        rA = 1;
    }
    bool tmpRend = rend;
    removeStyle(Style::VScroll | Style::HScroll | Style::Erlaubt);
    TextFeld::render(zRObj);
    if (!zRObj.setDrawOptions(innenPosition, innenSize))
    {
        if (rA) zRObj.releaseAlpha();
        setStyle(Style::Erlaubt, erlaubt);
        return;
    }
    if (hatStyle(Style::Sichtbar) && klickIndex == 1)
    {
        if (hatStyle(Style::KlickFarbe))
        {
            if (hatStyle(Style::KlickAlpha))
                zRObj.alphaRegion(0, 0, innenSize.x, innenSize.y, klickFarbe);
            else
                zRObj.fillRegion(0, 0, innenSize.x, innenSize.y, klickFarbe);
        }
        if (hatStyle(Style::KlickBild) && klickBild)
        {
            if (hatStyle(Style::KlickAlpha))
                zRObj.alphaBild(0, 0, innenSize.x, innenSize.y, *klickBild);
            else
                zRObj.drawBild(0, 0, innenSize.x, innenSize.y, *klickBild);
        }
        if (hatStyle(Style::KlickBuffer) && klickBuffer)
        {
            klickBuffer->setSize(innenSize.x, innenSize.y);
            klickBuffer->render(zRObj);
        }
    }
    if (rA) zRObj.releaseAlpha();
    zRObj.releaseDrawOptions();
    setStyle(Style::Erlaubt, erlaubt);
    rend = tmpRend;
}

// constant
int Knopf::getKlickFarbe() const // gibt getThis der Klick Farbe zurück
{
    return klickFarbe;
}

Bild* Knopf::getKlickBild() const // gibt getThis des Klick Bildes zurück
{
    if (!klickBild) return 0;
    return dynamic_cast<Bild*>(klickBild->getThis());
}

Bild* Knopf::zKlickBild() const // gibt einen Zeiger zum Klick Bild zurück
{
    return klickBild;
}

AlphaFeld* Knopf::getKB() const // gibt getThis des Klick Buffers zurück
{
    if (!klickBuffer) return 0;
    return dynamic_cast<AlphaFeld*>(klickBuffer->getThis());
}

AlphaFeld* Knopf::zKB() const // gibt den Klick Buffer zurück
{
    return klickBuffer;
}

int Knopf::getKBFarbe() const // gibt getThis der Farbe des Klick Buffers zurück
{
    if (!klickBuffer) return 0;
    return klickBuffer->getFarbe();
}

int Knopf::getKBStrength() const // gibt die Stärke des Klickbuffers zurück
{
    if (!klickBuffer) return 0;
    return klickBuffer->getStrength();
}

Zeichnung* Knopf::dublizieren() const // Erzeugt eine Kopie des Zeichnungs
{
    Knopf* obj = new Knopf();
    obj->setPosition(pos);
    obj->setSize(gr);
    obj->setMausEreignisParameter(makParam);
    obj->setTastaturEreignisParameter(takParam);
    obj->setMausEreignis(mak);
    obj->setTastaturEreignis(tak);
    if (toolTip) obj->setToolTipZ((ToolTip*)toolTip->dublizieren());
    obj->setStyle(style);
    obj->setSchriftSize(getSchriftSize());
    if (zSchrift()) obj->setSchriftZ(getSchrift());
    if (zText()) obj->setText(zText()->getText());
    obj->setHintergrundFarbe(hintergrundFarbe);
    obj->setSchriftFarbe(getSchriftFarbe());
    if (hintergrundFeld)
        obj->setAlphaFeldZ((AlphaFeld*)hintergrundFeld->dublizieren());
    if (rahmen) obj->setRahmenZ((Rahmen*)rahmen->dublizieren());
    if (hintergrundBild)
        obj->setHintergrundBild(
            dynamic_cast<Bild*>(hintergrundBild->getThis()));
    if (vertikalScrollBar)
    {
        obj->setVertikalKlickScroll(vertikalScrollBar->getKlickScroll());
        obj->setVertikalScrollPos(vertikalScrollBar->getScroll());
        obj->setVertikalScrollFarbe(
            vertikalScrollBar->getFarbe(), vertikalScrollBar->getBgFarbe());
    }
    if (horizontalScrollBar)
    {
        obj->setHorizontalKlickScroll(horizontalScrollBar->getKlickScroll());
        obj->setHorizontalScrollPos(horizontalScrollBar->getScroll());
        obj->setHorizontalScrollFarbe(
            horizontalScrollBar->getFarbe(), horizontalScrollBar->getBgFarbe());
    }
    obj->setSchowChar(getShowChar());
    // obj->setAuswahl( getSelectionPos(), getCursorPos() );
    obj->setKlickFarbe(klickFarbe);
    if (klickBild) obj->setKlickBild(dynamic_cast<Bild*>(klickBild->getThis()));
    if (klickBuffer) obj->setKBZ((AlphaFeld*)klickBuffer->dublizieren());
    return obj;
}

// Inhalt der KontrollKnopf Klasse aus Knopf.h
// Konstruktor
KontrollKnopf::KontrollKnopf()
    : ZeichnungHintergrund(),
      txt(0),
      sTxt(0),
      sBgF(0),
      kBgF(0),
      sBgB(0),
      kBgB(0),
      sAf(0),
      kAf(0),
      kasten(0),
      sKasten(0),
      textRd(0),
      sF(0xFFFFFFFF),
      sGr(12)
{
    style = Style::Erlaubt | Style::KlickBuffer;
    setKAFFarbe(0x00007500);
    setKAFStrength(-30);
}

// Destruktor
KontrollKnopf::~KontrollKnopf()
{
    if (txt) txt->release();
    if (sTxt) sTxt->release();
    if (sBgB) sBgB->release();
    if (kBgB) kBgB->release();
    if (sAf) sAf->release();
    if (kAf) kAf->release();
    if (kasten) kasten->release();
    if (sKasten) sKasten->release();
    if (textRd) textRd->release();
}

void KontrollKnopf::doMausEreignis(
    MausEreignis& me, bool userRet) // Nachrichten verarbeitung
{
    if (me.id == ME_Leaves || !userRet) style &= ~Style::MausKlick;
    if (hatStyleNicht(TextFeld::Style::Erlaubt) || !userRet) return;
    if (me.id == ME_Betritt && hatStyle(Style::MausKlick) != MausStand[M_Links])
        setStyle(Style::MausKlick, MausStand[M_Links]);
    if (me.id == ME_PLinks) addStyle(Style::MausKlick);
    if (me.id == ME_RLinks)
    {
        removeStyle(Style::MausKlick);
        setStyle(Style::Selected, !hatStyle(Style::Selected));
    }
    me.verarbeitet = 1;
}

// nicht constant
void KontrollKnopf::setTextZ(Text* txt) // setzt den Text
{
    if (this->txt) this->txt->release();
    this->txt = txt;
    rend = 1;
}

void KontrollKnopf::setText(Text* txt)
{
    if (!this->txt) this->txt = new Text();
    this->txt->setText(txt->getText());
    txt->release();
    rend = 1;
}

void KontrollKnopf::setText(const char* txt)
{
    if (!this->txt) this->txt = new Text();
    this->txt->setText(txt);
    rend = 1;
}

void KontrollKnopf::setSTextZ(Text* txt) // setzt den Text bei Selectiert
{
    if (sTxt) sTxt->release();
    sTxt = txt;
    rend = 1;
}

void KontrollKnopf::setSText(Text* txt)
{
    if (!sTxt) sTxt = new Text();
    sTxt->setText(txt->getText());
    txt->release();
    rend = 1;
}

void KontrollKnopf::setSText(const char* txt)
{
    if (!sTxt) sTxt = new Text();
    sTxt->setText(txt);
    rend = 1;
}

void KontrollKnopf::setTextRendererZ(TextRenderer* textRd)
{
    if (this->textRd) this->textRd->release();
    this->textRd = textRd;
}

void KontrollKnopf::setSchriftZ(Schrift* schrift) // setzt die Schrift
{
    if (!this->textRd)
        textRd = new TextRenderer(schrift);
    else
        textRd->setSchriftZ(schrift);
    rend = 1;
}

void KontrollKnopf::setSFarbe(int f) // setzt die Schrift Farbe
{
    sF = f;
    rend = 1;
}

void KontrollKnopf::setSSize(int gr) // setzt die Schrift Größe
{
    sGr = gr;
    rend = 1;
}

void KontrollKnopf::setSBgFarbe(int f) // setzt die Select Hintergrundfarbe
{
    sBgF = f;
    rend = 1;
}

void KontrollKnopf::setKBgFarbe(int f) // setzt die Klick Hintergrundfarbe
{
    kBgF = f;
    rend = 1;
}

void KontrollKnopf::setSBgBildZ(Bild* b) // setzt das Select Hintergrundbild
{
    if (sBgB) sBgB->release();
    sBgB = b;
    rend = 1;
}

void KontrollKnopf::setSBgBild(Bild* b)
{
    if (!sBgB) sBgB = new Bild();
    sBgB->neuBild(b->getBreite(), b->getHeight(), 0);
    sBgB->drawBild(0, 0, b->getBreite(), b->getHeight(), *b);
    b->release();
    rend = 1;
}

void KontrollKnopf::setKBgBildZ(Bild* b) // setzt das Klick Hintergrundbild
{
    if (kBgB) kBgB->release();
    kBgB = b;
    rend = 1;
}

void KontrollKnopf::setKBgBild(Bild* b)
{
    if (!kBgB) kBgB = new Bild();
    kBgB->neuBild(b->getBreite(), b->getHeight(), 0);
    kBgB->drawBild(0, 0, b->getBreite(), b->getHeight(), *b);
    b->release();
    rend = 1;
}

void KontrollKnopf::setSAlphaFeldZ(AlphaFeld* af) // setzt das Select Alpha Feld
{
    if (sAf) sAf->release();
    sAf = af;
    rend = 1;
}

void KontrollKnopf::setSAFFarbe(int f) // setzt die Select Alphafeld Farbe
{
    if (!sAf) sAf = new AlphaFeld();
    sAf->setFarbe(f);
    rend = 1;
}

void KontrollKnopf::setSAFStrength(int st) // setzt die Select AlphaFeld Stärke
{
    if (!sAf) sAf = new AlphaFeld();
    sAf->setStrength(st);
    rend = 1;
}

void KontrollKnopf::setKAlphaFeldZ(AlphaFeld* af) // setzt das Klick Alpha Feld
{
    if (kAf) kAf->release();
    kAf = af;
    rend = 1;
}

void KontrollKnopf::setKAFFarbe(int f) // setzt die Klick Alphafeld Farbe
{
    if (!kAf) kAf = new AlphaFeld();
    kAf->setFarbe(f);
    rend = 1;
}

void KontrollKnopf::setKAFStrength(int st) // setzt die Klick AlphaFeld Stärke
{
    if (!kAf) kAf = new AlphaFeld();
    kAf->setStrength(st);
    rend = 1;
}

void KontrollKnopf::loadData(LTDBDatei* dat) // läht die Systembilder
{
    if (DateiExistiert(new Text("data/normal.ltdb"))
        && (!dat || !dat->istOffen()))
    {
        LTDBDatei* dat = new LTDBDatei();
        dat->setDatei(new Text("data/normal.ltdb"));
        dat->leseDaten(0);
        kasten = dat->laden(0, new Text("kasten.gif"));
        sKasten = dat->laden(0, new Text("skasten.gif"));
        dat->release();
    }
    else
    {
        kasten = dat->laden(0, new Text("kasten.gif"));
        sKasten = dat->laden(0, new Text("skasten.gif"));
    }
    rend = 1;
}

void KontrollKnopf::loadData(const char* ltdb) // läht die Systembilder
{
    if (DateiExistiert(new Text(ltdb)))
    {
        LTDBDatei* dat = new LTDBDatei();
        dat->setDatei(new Text(ltdb));
        dat->leseDaten(0);
        kasten = dat->laden(0, new Text("kasten.gif"));
        sKasten = dat->laden(0, new Text("skasten.gif"));
        dat->release();
        rend = 1;
    }
}

void KontrollKnopf::render(Bild& zRObj) // zeichnet nach zRObj
{
    if (!hatStyle(Style::Sichtbar)) return;
    removeStyle(Style::VScroll | Style::HScroll);
    ZeichnungHintergrund::render(zRObj);
    lockZeichnung();
    if (!zRObj.setDrawOptions(innenPosition, innenSize))
    {
        unlockZeichnung();
        return;
    }
    if (hatStyle(Style::MausKlick))
    {
        if (hatStyle(Style::KlickFarbe))
        {
            if (hatStyle(Style::KlickAlpha))
                zRObj.alphaRegion(0, 0, innenSize.x, innenSize.y, kBgF);
            else
                zRObj.fillRegion(0, 0, innenSize.x, innenSize.y, kBgF);
        }
        if (hatStyle(Style::KlickBild) && kBgB)
        {
            if (hatStyle(Style::KlickAlpha))
                zRObj.alphaBild(0, 0, innenSize.x, innenSize.y, *kBgB);
            else
                zRObj.drawBild(0, 0, innenSize.x, innenSize.y, *kBgB);
        }
        if (hatStyle(Style::KlickBuffer) && kAf)
        {
            kAf->setSize(innenSize.x, innenSize.y);
            kAf->render(zRObj);
        }
        int kbr = 0;
        if (hatStyle(Style::Selected) && sKasten)
        {
            if (sTxt && textRd)
                zRObj.drawBild(0,
                    (gr.y / 2 - sKasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - sKasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *sKasten);
            else
                zRObj.drawBild(gr.x / 2 - sKasten->getBreite() / 2,
                    (gr.y / 2 - sKasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - sKasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *sKasten);
            kbr = sKasten->getBreite();
            if (sTxt && textRd)
            {
                textRd->setSchriftSize(sGr);
                textRd->renderText(kbr + 5,
                    gr.y / 2 - textRd->getTextHeight(sTxt->getText()) / 2,
                    sTxt->getText(),
                    zRObj,
                    sF);
            }
        }
        else if (kasten)
        {
            if (txt && textRd)
                zRObj.drawBild(0,
                    (gr.y / 2 - kasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - kasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *kasten);
            else
                zRObj.drawBild(gr.x / 2 - kasten->getBreite() / 2,
                    (gr.y / 2 - kasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - kasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *kasten);
            kbr = kasten->getBreite();
            if (txt && textRd)
            {
                textRd->setSchriftSize(sGr);
                textRd->renderText(kbr + 5,
                    gr.y / 2 - textRd->getTextHeight(txt->getText()) / 2,
                    txt->getText(),
                    zRObj,
                    sF);
            }
        }
    }
    else if (hatStyle(Style::Selected))
    {
        if (hatStyle(Style::SelectFarbe))
        {
            if (hatStyle(Style::SelectAlpha))
                zRObj.alphaRegion(0, 0, innenSize.x, innenSize.y, sBgF);
            else
                zRObj.fillRegion(0, 0, innenSize.x, innenSize.y, sBgF);
        }
        if (hatStyle(Style::SelectBild) && sBgB)
        {
            if (hatStyle(Style::SelectAlpha))
                zRObj.alphaBild(0, 0, innenSize.x, innenSize.y, *sBgB);
            else
                zRObj.drawBild(0, 0, innenSize.x, innenSize.y, *sBgB);
        }
        if (hatStyle(Style::SelectBuffer) && sAf)
        {
            sAf->setSize(innenSize.x, innenSize.y);
            sAf->render(zRObj);
        }
        int kbr = 0;
        if (sKasten)
        {
            if (sTxt && textRd)
                zRObj.drawBild(0,
                    (gr.y / 2 - sKasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - sKasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *sKasten);
            else
                zRObj.drawBild(gr.x / 2 - sKasten->getBreite() / 2,
                    (gr.y / 2 - sKasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - sKasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *sKasten);
            kbr = sKasten->getBreite();
        }
        if (sTxt && textRd)
        {
            textRd->setSchriftSize(sGr);
            textRd->renderText(kbr + 5,
                gr.y / 2 - textRd->getTextHeight(sTxt->getText()) / 2,
                sTxt->getText(),
                zRObj,
                sF);
        }
    }
    else
    {
        int kbr = 0;
        if (kasten)
        {
            if (txt && textRd)
                zRObj.drawBild(0,
                    (gr.y / 2 - kasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - kasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *kasten);
            else
                zRObj.drawBild(gr.x / 2 - kasten->getBreite() / 2,
                    (gr.y / 2 - kasten->getHeight() / 2) < 0
                        ? 0
                        : (gr.y / 2 - kasten->getHeight() / 2),
                    innenSize.x,
                    innenSize.y,
                    *kasten);
            kbr = kasten->getBreite();
        }
        if (txt && textRd)
        {
            textRd->setSchriftSize(sGr);
            textRd->renderText(kbr + 5,
                gr.y / 2 - textRd->getTextHeight(txt->getText()) / 2,
                txt->getText(),
                zRObj,
                sF);
        }
    }
    zRObj.releaseDrawOptions();
    unlockZeichnung();
}

// constant
Text* KontrollKnopf::getText() const // gibt den Text zurück
{
    return txt ? dynamic_cast<Text*>(txt->getThis()) : 0;
}

Text* KontrollKnopf::zText() const
{
    return txt;
}

Text* KontrollKnopf::getSText() const // gibt den Select Text zurück
{
    return sTxt ? dynamic_cast<Text*>(sTxt->getThis()) : 0;
}

Text* KontrollKnopf::zSText() const
{
    return sTxt;
}

Schrift* KontrollKnopf::getSchrift() const // gibt die Schrift zurück
{
    return textRd ? textRd->getSchrift() : 0;
}

Schrift* KontrollKnopf::zSchrift() const
{
    return textRd ? textRd->zSchrift() : 0;
}

int KontrollKnopf::getSFarbe() const // gibt die Schrift Farbe zurück
{
    return sF;
}

int KontrollKnopf::getSSize() const // gibt die Schrift Größe zurück
{
    return sGr;
}

int KontrollKnopf::getSBgFarbe()
    const // gibt die Select Hintergrundfarbe zurück
{
    return sBgF;
}

int KontrollKnopf::getKBgFarbe() const // gibt die Klick Hintergrundfarbe zurück
{
    return kBgF;
}

Bild* KontrollKnopf::getSBgBild()
    const // gibt das Select Hintergrundbild zurück
{
    return sBgB ? dynamic_cast<Bild*>(sBgB->getThis()) : 0;
}

Bild* KontrollKnopf::zSBgBild() const
{
    return sBgB;
}

Bild* KontrollKnopf::getKBgBild() const // gibt das Klick Hintergrundbild zurück
{
    return kBgB ? dynamic_cast<Bild*>(kBgB->getThis()) : 0;
}

Bild* KontrollKnopf::zKBgBild() const
{
    return kBgB;
}

AlphaFeld*
KontrollKnopf::getSAlphaFeld() const // gibt das Select AlphaFeld zurück
{
    return sAf ? dynamic_cast<AlphaFeld*>(sAf->getThis()) : 0;
}

AlphaFeld* KontrollKnopf::zSAlphaFeld() const
{
    return sAf;
}

AlphaFeld*
KontrollKnopf::getKAlphaFeld() const // gibt das Klick AlphaFeld zurück
{
    if (!kAf) return 0;
    return dynamic_cast<AlphaFeld*>(kAf->getThis());
}

AlphaFeld* KontrollKnopf::zKAlphaFeld() const
{
    return kAf;
}