#include "Scroll.h"

#include "Bild.h"
#include "MausEreignis.h"

using namespace Framework;

// Inhalt der VScrollBar Klasse aus Scroll.h
// Konstruktor
ScrollBar::ScrollBar()
    : ReferenceCounter(),
      data(new ScrollData()),
      knopfdruck(0),
      farbe(0xFF808080),
      bgFarbe(0xFF000000),
      bg(0),
      klickScroll(10),
      mx(-1),
      my(-1),
      mp(0),
      rend(0)
{}

// Destruktor
ScrollBar::~ScrollBar()
{
    delete data;
}

// nicht constant
void ScrollBar::setFarbe(int fc)
{
    farbe = fc;
    rend = 1;
}

void ScrollBar::setBgFarbe(int fc, bool bgF)
{
    bgFarbe = fc;
    bg = bgF;
    rend = 1;
}

void ScrollBar::update(int maxGr, int anzeigeGr)
{
    if (data->max != maxGr || data->anzeige != anzeigeGr)
    {
        data->max = maxGr, data->anzeige = anzeigeGr;
        rend = 1;
    }
    if (data->scrollPos > data->max - data->anzeige
        && data->max - data->anzeige >= 0)
    {
        data->scrollPos = data->max - data->anzeige;
        rend = 1;
    }
    if (data->scrollPos < 0)
    {
        data->scrollPos = 0;
        rend = 1;
    }
}

void ScrollBar::setKlickScroll(int ks)
{
    klickScroll = ks;
    rend = 1;
}

void ScrollBar::scroll(int height)
{
    data->scrollPos = height;
    if (data->scrollPos > data->max - data->anzeige)
        data->scrollPos = data->max - data->anzeige;
    if (data->scrollPos < 0) data->scrollPos = 0;
    rend = 1;
}

bool ScrollBar::getRend()
{
    if (knopfdruck == 1)
    {
        int tmp = data->scrollPos;
        data->scrollPos -= klickScroll;
        if (data->scrollPos > data->max - data->anzeige)
            data->scrollPos = data->max - data->anzeige;
        if (data->scrollPos < 0) data->scrollPos = 0;
        if (tmp != data->scrollPos) rend = 1;
    }
    if (knopfdruck == 2)
    {
        int tmp = data->scrollPos;
        data->scrollPos += klickScroll;
        if (data->scrollPos > data->max - data->anzeige)
            data->scrollPos = data->max - data->anzeige;
        if (data->scrollPos < 0) data->scrollPos = 0;
        if (tmp != data->scrollPos) rend = 1;
    }
    bool ret = rend;
    rend = 0;
    return ret;
}

// const
ScrollData* ScrollBar::getScrollData() const
{
    return data;
}

int ScrollBar::getKlickScroll() const
{
    return klickScroll;
}

int ScrollBar::getFarbe() const
{
    return farbe;
}

int ScrollBar::getBgFarbe() const
{
    return bg ? bgFarbe : 0;
}

int ScrollBar::getScroll() const
{
    return data->scrollPos;
}

// Inhalt der VScrollBar Klasse
VScrollBar::VScrollBar()
    : ScrollBar()
{}

// Destruktor
VScrollBar::~VScrollBar() {}

bool VScrollBar::doMausMessage(int x, int y, int br, int hi, MausEreignis& me)
{
    if (me.id == ME_Leaves)
    {
        mp = 0;
        mx = -1;
        my = -1;
    }
    bool ret = me.mx >= x && me.mx <= x + br && me.my >= y && me.my <= y + hi;
    knopfdruck = 0;
    if (me.verarbeitet)
    {
        mx = -1, my = -1;
        mp = 0;
        return ret;
    }
    if (me.id == ME_UScroll)
    {
        data->scrollPos -= klickScroll;
        if (data->scrollPos < 0) data->scrollPos = 0;
        rend = 1;
        return ret;
    }
    if (me.id == ME_DScroll)
    {
        data->scrollPos += klickScroll;
        if (data->scrollPos > data->max - data->anzeige)
            data->scrollPos = data->max - data->anzeige;
        if (data->scrollPos < 0) data->scrollPos = 0;
        rend = 1;
        return ret;
    }
    if (ret)
        mx = me.mx - x, my = me.my - y;
    else
        mx = -1, my = -1;
    if (me.id == ME_PLinks) mp = 1;
    if (me.id == ME_RLinks) mp = 0;
    if (mp)
    {
        if (mx >= 0 && my >= 0)
        {
            if (my < br)
            {
                knopfdruck = 1;
                data->scrollPos -= klickScroll;
            }
            else if (my > hi - br)
            {
                knopfdruck = 2;
                data->scrollPos += klickScroll;
            }
            else
                data->scrollPos
                    = (int)((data->max / (hi - 2.0 * br)) * (my - br))
                    - data->anzeige / 2;
            if (data->scrollPos > data->max - data->anzeige)
                data->scrollPos = data->max - data->anzeige;
            if (data->scrollPos < 0) data->scrollPos = 0;
            rend = 1;
        }
    }
    return ret;
}

void VScrollBar::render(int x, int y, int br, int hi, Bild& zRObj) const
{
    if (bg) zRObj.alphaRegion(x, y, br, hi, bgFarbe);
    --br;
    --hi;
    zRObj.drawLinieH(x, y, br + 1, farbe);
    zRObj.drawLinieH(x, y + hi, br + 1, farbe);
    zRObj.drawLinieV(x, y + 1, hi - 1, farbe);
    zRObj.drawLinieV(x + br, y + 1, hi - 1, farbe);
    zRObj.drawLinieH(x + 1, y + br, br - 1, farbe);
    zRObj.drawLinieH(x + 1, y + hi - br, br - 1, farbe);
    ++br;
    ++hi;
    int st = (int)(data->scrollPos / (data->max / (hi - br * 2.0)));
    int end = (int)((hi - 2.0 * br) / ((double)data->max / data->anzeige));
    if (data->scrollPos > data->max - data->anzeige)
        data->scrollPos = data->max - data->anzeige;
    if (data->scrollPos < 0)
    {
        data->scrollPos = 0;
        end = hi - br * 2;
    }
    zRObj.fillRegion(x + 1, y + br + st, br - 1, end, farbe);
}

// Inhalt der HScrollBar Klasse aus Scroll.h
// Konstruktor
HScrollBar::HScrollBar()
    : ScrollBar()
{}

// Destruktor
HScrollBar::~HScrollBar() {}

// nicht constant
bool HScrollBar::doMausMessage(int x, int y, int br, int hi, MausEreignis& me)
{
    if (me.id == ME_Leaves)
    {
        mp = 0;
        mx = -1;
        my = -1;
    }
    bool ret = me.mx >= x && me.mx <= x + br && me.my >= y && me.my <= y + hi;
    knopfdruck = 0;
    if (me.verarbeitet)
    {
        mx = -1, my = -1;
        mp = 0;
        return ret;
    }
    if (me.id == ME_LScroll)
    {
        data->scrollPos -= klickScroll;
        if (data->scrollPos < 0) data->scrollPos = 0;
        rend = 1;
        return ret;
    }
    if (me.id == ME_RScroll)
    {
        data->scrollPos += klickScroll;
        if (data->scrollPos > data->max - data->anzeige)
            data->scrollPos = data->max - data->anzeige;
        if (data->scrollPos < 0) data->scrollPos = 0;
        rend = 1;
        return ret;
    }
    if (ret)
        mx = me.mx - x, my = me.my - y;
    else
        mx = -1, my = -1;
    if (me.id == ME_PLinks) mp = 1;
    if (me.id == ME_RLinks) mp = 0;
    if (mp)
    {
        if (mx >= 0 && my >= 0)
        {
            if (mx < hi)
            {
                knopfdruck = 1;
                data->scrollPos -= klickScroll;
            }
            else if (mx > br - hi)
            {
                knopfdruck = 2;
                data->scrollPos += klickScroll;
            }
            else
                data->scrollPos
                    = (int)((data->max / (br - 2.0 * hi)) * (mx - hi))
                    - data->anzeige / 2;
            if (data->scrollPos > data->max - data->anzeige)
                data->scrollPos = data->max - data->anzeige;
            if (data->scrollPos < 0) data->scrollPos = 0;
            rend = 1;
        }
    }
    return ret;
}

void HScrollBar::render(int x, int y, int br, int hi, Bild& zRObj) const
{
    if (bg) zRObj.alphaRegion(x, y, br, hi, bgFarbe);
    --br;
    --hi;
    zRObj.drawLinieV(x, y, hi + 1, farbe);
    zRObj.drawLinieV(x + br, y, hi + 1, farbe);
    zRObj.drawLinieH(x + 1, y, br - 1, farbe);
    zRObj.drawLinieH(x + 1, y + hi, br - 1, farbe);
    zRObj.drawLinieV(x + hi, y + 1, hi - 1, farbe);
    zRObj.drawLinieV(x + br - hi, y + 1, hi - 1, farbe);
    ++br;
    ++hi;
    int st = (int)(data->scrollPos / (data->max / (br - hi * 2.0)));
    int end = (int)((br - 2.0 * hi) / ((double)data->max / data->anzeige));
    if (data->scrollPos > data->max - data->anzeige)
        data->scrollPos = data->max - data->anzeige;
    if (data->scrollPos < 0)
    {
        data->scrollPos = 0;
        end = br - hi * 2;
    }
    zRObj.fillRegion(x + hi + st, y + 1, end, hi - 1, farbe);
}