#include "Mouse.h"

#include "Image.h"
#include "Point.h"

using namespace Framework;

// Contents of the Mouse class from Mouse.h
// Constructor
Mouse::Mouse()
    : ReferenceCounter(),
      hMouse(LoadCursor(0, IDC_ARROW))
{}

// non-constant
void Mouse::loadMouse(int mouseId)
{
    if (mouseId == MouseId::nichts) hMouse = 0;
    if (mouseId == MouseId::normal) hMouse = LoadCursor(0, IDC_ARROW);
    if (mouseId == MouseId::hand) hMouse = LoadCursor(0, IDC_HAND);
    if (mouseId == MouseId::warten) hMouse = LoadCursor(0, IDC_APPSTARTING);
    if (mouseId == MouseId::verschieben) hMouse = LoadCursor(0, IDC_SIZEALL);
    if (mouseId == MouseId::text) hMouse = LoadCursor(0, IDC_IBEAM);
    if (mouseId == MouseId::wahgerecht) hMouse = LoadCursor(0, IDC_SIZEWE);
    if (mouseId == MouseId::senkrecht) hMouse = LoadCursor(0, IDC_SIZENS);
    if (mouseId == MouseId::diagonal1) hMouse = LoadCursor(0, IDC_SIZENWSE);
    if (mouseId == MouseId::diagonal2) hMouse = LoadCursor(0, IDC_SIZENESW);
    if (mouseId == MouseId::verboten) hMouse = LoadCursor(0, IDC_NO);
    SetCursor(hMouse);
}

void Mouse::loadMouse(Image* mouse)
{
    HBITMAP hAndMaskBitmap;
    HBITMAP hXorMaskBitmap;
    HDC hDC = GetDC(0);
    HDC hAndMaskDC = CreateCompatibleDC(hDC);
    HDC hXorMaskDC = CreateCompatibleDC(hDC);

    hAndMaskBitmap
        = CreateCompatibleBitmap(hDC, mouse->getWidth(), mouse->getHeight());
    hXorMaskBitmap
        = CreateCompatibleBitmap(hDC, mouse->getWidth(), mouse->getHeight());

    // Select the bitmaps to DC
    HBITMAP hOldAndMaskBitmap
        = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
    HBITMAP hOldXorMaskBitmap
        = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);

    // Scan each pixel of the souce bitmap and create the masks
    int y;
    for (int x = 0; x < mouse->getWidth(); ++x)
    {
        for (y = 0; y < mouse->getHeight(); ++y)
        {
            int pixel = mouse->getPixel(x, y);
            if (((pixel >> 24) & 0xFF) == 0)
            {
                SetPixel(hAndMaskDC, x, y, RGB(255, 255, 255));
                SetPixel(hXorMaskDC, x, y, RGB(0, 0, 0));
            }
            else
            {
                SetPixel(hAndMaskDC, x, y, RGB(0, 0, 0));
                SetPixel(hXorMaskDC,
                    x,
                    y,
                    RGB((pixel >> 16) & 0xFF,
                        (pixel >> 8) & 0xFF,
                        pixel & 0xFF));
            }
        }
    }
    SelectObject(hAndMaskDC, hOldAndMaskBitmap);
    SelectObject(hXorMaskDC, hOldXorMaskBitmap);

    DeleteDC(hXorMaskDC);
    DeleteDC(hAndMaskDC);
    ReleaseDC(0, hDC);

    ICONINFO iconinfo = {0};
    iconinfo.fIcon = 0;
    iconinfo.xHotspot = 0;
    iconinfo.yHotspot = 0;
    iconinfo.hbmMask = hAndMaskBitmap;
    iconinfo.hbmColor = hXorMaskBitmap;
    hMouse = CreateIconIndirect(&iconinfo);

    SetCursor(hMouse);
}

void Mouse::update()
{
    SetCursor(hMouse);
}

// constant
HCURSOR Mouse::getMouseHandle()
{
    return hMouse;
}