// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifndef BARSHADER_H
#define BARSHADER_H

#include "wintypes.h"                       // DWORD - audited 4 Nov 2004

#include <stdint.h>                         // uint32_t
#include <wx/dc.h>
#include <wx/dcmemory.h>

#define RGB(a,b,c) ((a&0xff)<<16|(b&0xff)<<8|(c&0xff))

class CBarShader
{
public:
    CBarShader(uint32_t height = 1, uint32_t width = 1);
    ~CBarShader(void);

    //set the width of the bar
    void SetWidth(int width)
    {
        if (m_iWidth != width) 
        {
            m_iWidth = width;
            SetScaling();
        }
    }

    //set the height of the bar
    void SetHeight(int height)
    {
        if (m_iHeight != height)
        {
            m_iHeight = height;

            BuildModifiers();
        }
    }

    //returns the width of the bar
    int GetWidth()
    {
        return m_iWidth;
    }

    //returns the height of the bar
    int GetHeight()
    {
        return m_iHeight;
    }

    //call this to blank the shaderwithout changing file size
    void Reset();

    //sets new file size and resets the shader
    void SetFileSize(uint32_t fileSize);

    //fills in a range with a certain color, new ranges overwrite old
    void FillRange(uint32_t start, uint32_t end, DWORD color);

    //fills in entire range with a certain color
    void Fill(DWORD color);

    //draws the bar
    void Draw(wxDC* dc, int iLeft, int iTop, bool bFlat);

protected:
    void BuildModifiers();
    void FillRect(wxDC* dc, RECT* rectSpan, float fRed, float fGreen, float fBlue, bool bFlat);
    void FillRect(wxDC* dc, RECT* rectSpan, DWORD color, bool bFlat);
    void SetScaling(void);

    int    m_iWidth;
    int    m_iHeight;
    double m_dPixelsPerByte;
    double m_dBytesPerPixel;
    uint32_t m_uFileSize;

private:
    struct BarSpan
    {
        uint32_t start;
        uint32_t end;
        DWORD color;
        BarSpan *next;

        BarSpan(uint32_t s, uint32_t e, DWORD cr = RGB(0, 0, 0))
        {
            start = s;
            end = e;
            color = cr;
            next = NULL;
        }

        BarSpan(BarSpan* prev, uint32_t s, uint32_t e, DWORD cr)
        {
            start = s;
            end = e;
            color = cr;
            next = prev->next;
            prev->next = this;
        }

        void DeleteNext()
        {
            BarSpan* del = next;
            next = next->next;
            delete del;
        }

        void DeleteUpTo(BarSpan* last)
        {
            BarSpan* del = next;
            BarSpan* temp;
            while(del != last)
            {
                temp = del->next;
                delete del;
                del = temp;
            }
            next = last;
        }

    };

    BarSpan* m_FirstSpan;
    float* m_Modifiers;
    uint16_t m_used3dlevel;
};

#endif

