// DUiListBox.cpp: implementation of the CDUiListBox class.
//
//////////////////////////////////////////////////////////////////////

#include "DUiMan.h"
#include "DirectXHelpers.h"

BOOL g_bMoveWindow = FALSE;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDUiListBox::CDUiListBox()
{
    SetObjectType(DUI_LISTBOX);

    m_dwStringArraySize = 100;
    m_pStrings = (STRINGINFO *) malloc(sizeof(STRINGINFO)*m_dwStringArraySize);
    memset(m_pStrings,0,sizeof(STRINGINFO)*m_dwStringArraySize);
    m_dwStringCount = 0;

    m_dwSelectedString = 0xFFFFFFFF;
    m_dwFirstVisibleString = 0;
    m_dwLineCount = 0;
    m_dwFontWidth = 0;
    m_dwFontHeight = 0;
}

CDUiListBox::~CDUiListBox()
{
}

DWORD CDUiListBox::Display(BOOL bRefresh)
{
    DWORD       dwRetVal = 0;
    HRESULT     hr;
    DDBLTFX     ddbltfx;
    RECT        rSource;

    rSource.left = m_xPos;
    rSource.top = m_yPos;
    rSource.right = m_xPos + m_dwWidth;
    rSource.bottom = m_yPos + m_dwHeight;

    memset(&ddbltfx,0,sizeof(DDBLTFX));
    ddbltfx.dwSize = sizeof(DDBLTFX);
    //draw the outline in a color between the color of the background 
    //and either white or black depending on which is furthest
    ddbltfx.dwFillColor = GetFadeColor(m_dwBackgroundColor,5);
    hr = m_pddsMain->Blt(&rSource, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);

    rSource.left += 1;
    rSource.top += 1;
    rSource.right -= 1;
    rSource.bottom -= 1;

    //draw the background
    ddbltfx.dwFillColor = m_dwBackgroundColor;
    hr = m_pddsMain->Blt(&rSource, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);

    return dwRetVal;
}

DWORD CDUiListBox::DisplayText(BOOL bRefresh)
{
    DWORD dwRetVal = 0;
    HDC         dc;
    WCHAR       wszTemp[512];
    DWORD       dwTemp,dwTop,dwLeft,i;
    RECT        rSource;
    SIZE        size;
    rSource.left = m_xPos - 1;
    rSource.top = m_yPos + 1;
    rSource.right = m_xPos + m_dwWidth;
    rSource.bottom = m_yPos + m_dwHeight;

    if (g_pDUiManager->GetDC(&dc))
    {
        SelectObject(dc,m_pFont->GetFont());
        SetBkMode(dc,OPAQUE);
        SetBkColor(dc,ColorToColorRef(m_dwBackgroundColor));
        SetTextColor(dc,ColorToColorRef(m_dwFontColor));
        
        dwLeft = rSource.left+4;
        dwTop = rSource.top;

        //Figure out how many lines will fit on the screen
        if (m_dwStringCount > 1)
        {
            if (GetTextExtentPoint32(dc,m_pStrings[0].wszString,wcslen(m_pStrings[0].wszString),&size))
            {
                m_dwFontHeight = size.cy + 5; // 5 for buffer between lines
            }
            dwTemp = m_dwHeight - 10 + 5;
            m_dwLineCount = dwTemp / m_dwFontHeight + 1;
            if (m_dwSelectedString == 0xFFFFFFFF)
            {
                m_dwFirstVisibleString = 0;
            }
            else if ((m_dwLineCount + m_dwFirstVisibleString) < m_dwSelectedString)
            {
                m_dwFirstVisibleString = m_dwSelectedString - m_dwLineCount;
            }
        }

        for (i = m_dwFirstVisibleString; i < m_dwStringCount; i++)
        {
            if (GetTextExtentPoint32(dc,m_pStrings[i].wszString,wcslen(m_pStrings[i].wszString),&size))
            {
                //hack see what characters should actually be visible
                wcscpy(wszTemp,m_pStrings[i].wszString);
                if ((int)(dwTop + m_dwFontHeight) < rSource.bottom)
                {
                    if (i == m_dwSelectedString)
                        SetBkColor(dc,ColorToColorRef(m_dwSelectedFontColor));
                    ExtTextOut(dc,dwLeft,dwTop,ETO_OPAQUE,NULL,wszTemp,wcslen(wszTemp),NULL);
                    dwTop += size.cy + 2;
                    if (i == m_dwSelectedString)
                        SetBkColor(dc,ColorToColorRef(m_dwBackgroundColor));
                }
                else
                {
                    break;
                }
            }
        }
    }

    return dwRetVal;
}

DWORD CDUiListBox::OnKey(UINT nChar, UINT nFlags)
{
    int iTemp = 0;
    switch (nChar)
    {
    case VK_UP:
        if (g_bMoveWindow)
        {
            m_yPos--;
            break;
        }
        if (m_dwSelectedString == 0xFFFFFFFF)
        {
            m_dwSelectedString = 0;
        }
        else if (m_dwSelectedString > 0)
        {
            m_dwSelectedString--;
            OutputDebugString(L"Sending selchanged message\r\n");
        }
        if (m_dwFirstVisibleString > m_dwSelectedString)
        {
            m_dwFirstVisibleString = m_dwSelectedString;
        }
        PostMessage(g_pDUiManager->GetAppHWnd(),DUIM_LISTBOX_SELCHANGE,(WPARAM)this,0);
        break;
    case VK_DOWN:
        if (g_bMoveWindow)
        {
            m_yPos++;
            break;
        }
        if (m_dwSelectedString == 0xFFFFFFFF)
        {
            m_dwSelectedString = 0;
        }
        else if ((m_dwSelectedString + 1) < m_dwStringCount)
        {
            m_dwSelectedString++;
        }
        PostMessage(g_pDUiManager->GetAppHWnd(),DUIM_LISTBOX_SELCHANGE,(WPARAM)this,0);
        break;
    case VK_PRIOR:
        if (m_dwSelectedString == 0xFFFFFFFF)
        {
            m_dwSelectedString = 0;
        }
        else if (m_dwSelectedString > m_dwLineCount)
        {
            m_dwSelectedString -= m_dwLineCount;
        }
        else
        {
            m_dwSelectedString = 0;
        }
        if (m_dwSelectedString < m_dwFirstVisibleString)
        {
            m_dwFirstVisibleString = m_dwSelectedString;
        }
        PostMessage(g_pDUiManager->GetAppHWnd(),DUIM_LISTBOX_SELCHANGE,(WPARAM)this,0);
        break;
    case VK_NEXT:
        if (m_dwSelectedString == 0xFFFFFFFF)
        {
            m_dwSelectedString = 0;
            iTemp = -1;
        }
        if ((m_dwSelectedString + m_dwLineCount) < m_dwStringCount)
        {
            m_dwSelectedString += (m_dwLineCount + iTemp);
        }
        else
        {
            m_dwSelectedString = m_dwStringCount - 1;
        }
        PostMessage(g_pDUiManager->GetAppHWnd(),DUIM_LISTBOX_SELCHANGE,(WPARAM)this,0);
        break;
    case VK_LEFT:
        if (g_bMoveWindow)
        {
            m_xPos--;
            break;
        }
        //TODO scroll left if possible
        break;
    case VK_RIGHT:
        if (g_bMoveWindow)
        {
            m_xPos++;
            break;
        }
        //TODO scroll right if possible
        break;
    case VK_RETURN:
        PostMessage(g_pDUiManager->GetAppHWnd(),DUIM_ENTER,(WPARAM)this,0);
        break;
    case VK_F4:
//        g_bMoveWindow = !g_bMoveWindow;
        break;
    }
    return 0;
}

DWORD CDUiListBox::OnChar(UINT nChar, UINT nFlags)
{
    switch (nChar)
    {
    case 'c':
    case 'C':
        if ((HIWORD(nFlags) & KF_ALTDOWN) && (m_dwStyle & DUIS_LISTBOX_ALLOW_CLEAR))
        {
            this->Reset();
        }
        break;
    }
    return 0;
}

DWORD CDUiListBox::Initialize()
{
    //hack figure out how to get width and height of font
    m_dwFontHeight = 15;
    m_dwFontWidth = 5;

    return 0;
}

DWORD CDUiListBox::AddString(WCHAR *wszString, DWORD dwData)
{
    DWORD i;
    STRINGINFO *pTemp = NULL;
    if (m_dwStringCount >= m_dwStringArraySize)
    {
        m_dwStringArraySize += 100;
        m_pStrings = (STRINGINFO *) realloc(m_pStrings,sizeof(STRINGINFO)*m_dwStringArraySize);
        for (i = m_dwStringCount; i < m_dwStringArraySize; i++)
        {
            m_pStrings[i].dwStringSize = 0;
            m_pStrings[i].wszString = 0;
        }
//        memset(m_pStrings+m_dwStringArraySize-10,0,sizeof(STRINGINFO)*10);
    }

    ///create the string info struct if it doesn't exist
/*    if (!m_pStrings[m_dwStringCount])
    {
        pTemp = m_pStrings[m_dwStringCount] = (STRINGINFO *)malloc(sizeof(STRINGINFO));
        pTemp->wszString = NULL;
        pTemp->dwStringSize = 0;
    }
    else
    {
        pTemp = m_pStrings[m_dwStringCount]
    }
*/
    pTemp = &m_pStrings[m_dwStringCount];
    //see if the currently allocated string length is enough to hold this string
    if (pTemp->dwStringSize <= (wcslen(wszString) + 1))
    {
        pTemp->dwStringSize = wcslen(wszString) + 1;
        if (pTemp->dwStringSize < 256)
            pTemp->dwStringSize = 256;
        pTemp->wszString = (WCHAR *) realloc(pTemp->wszString,pTemp->dwStringSize);
    }
        
    wcscpy(pTemp->wszString,wszString);
    pTemp->dwData = dwData;
    m_dwStringCount++;

    return m_dwStringCount-1;
}

BOOL  CDUiListBox::GetString(DWORD dwIndex, WCHAR *wszString)
{
    BOOL bRetVal = FALSE;
    *wszString = 0;

    if ((dwIndex < m_dwStringCount) && m_pStrings[dwIndex].wszString)
    {
        wcscpy(wszString,m_pStrings[dwIndex].wszString);
        bRetVal = TRUE;
    }

    return bRetVal;
}

BOOL  CDUiListBox::GetData(DWORD dwIndex, DWORD *pdwData)
{
    BOOL bRetVal = FALSE;

    if ((dwIndex < m_dwStringCount) && m_pStrings[dwIndex].wszString)
    {
        *pdwData = m_pStrings[dwIndex].dwData;
        bRetVal = TRUE;
    }

    return bRetVal;
}

BOOL  CDUiListBox::RemoveString(DWORD dwIndex)
{
    BOOL bRetVal = FALSE;

    return bRetVal;
}

BOOL  CDUiListBox::Reset()
{
    BOOL bRetVal = FALSE;

    m_dwStringCount = 0;
    m_dwFirstVisibleString = 0;
    m_dwSelectedString = 0xFFFFFFFF;

    return bRetVal;
}
