#include "SnarlInterface.h"

#include <QtCore>
#include <stdlib.h>
#include <string>

using namespace std;

SnarlInterface::SnarlInterface() { SNARL_GLOBAL_MESSAGE = "SnarlGlobalMessage"; }

SnarlInterface::~SnarlInterface() { }

long SnarlInterface::snShowMessage(std::string title, std::string text, long timeout, std::string iconPath,
                                   HWND hWndReply, long uReplyMsg)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.cmd = SNARL_SHOW;
    if (title.length() > SNARL_STRING_LENGTH) {
        strcpy(snarlStruct.title, (title.substr(0, SNARL_STRING_LENGTH - 1)).c_str());
    } else {
        strcpy(snarlStruct.title, title.c_str());
    }
    if (text.length() > SNARL_STRING_LENGTH) {
        strcpy(snarlStruct.text, (text.substr(0, SNARL_STRING_LENGTH - 1)).c_str());
    } else {
        strcpy(snarlStruct.text, text.c_str());
    }
    if (iconPath.length() > SNARL_STRING_LENGTH) {
        strcpy(snarlStruct.icon, (iconPath.substr(0, SNARL_STRING_LENGTH - 1)).c_str());
    } else {
        strcpy(snarlStruct.icon, iconPath.c_str());
    }
    snarlStruct.timeout  = timeout;
    snarlStruct.lngData2 = reinterpret_cast<long>(hWndReply);
    snarlStruct.id       = uReplyMsg;
    return send(snarlStruct);
}

bool SnarlInterface::snHideMessage(long id)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.id  = id;
    snarlStruct.cmd = SNARL_HIDE;
    return bool(send(snarlStruct));
}

bool SnarlInterface::snIsMessageVisible(long id)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.id  = id;
    snarlStruct.cmd = SNARL_IS_VISIBLE;
    return bool(send(snarlStruct));
}

bool SnarlInterface::snUpdateMessage(long id, std::string title, std::string text)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.id  = id;
    snarlStruct.cmd = SNARL_UPDATE;
    if (title.length() > SNARL_STRING_LENGTH) {
        strcpy(snarlStruct.title, (title.substr(0, SNARL_STRING_LENGTH - 1)).c_str());
    } else {
        strcpy(snarlStruct.title, title.c_str());
    }
    if (text.length() > SNARL_STRING_LENGTH) {
        strcpy(snarlStruct.text, (text.substr(0, SNARL_STRING_LENGTH - 1)).c_str());
    } else {
        strcpy(snarlStruct.text, text.c_str());
    }
    return bool(send(snarlStruct));
}

bool SnarlInterface::snRegisterConfig(HWND hWnd, std::string appName, long replyMsg)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.cmd      = SNARL_REGISTER_CONFIG_WINDOW;
    snarlStruct.lngData2 = reinterpret_cast<long>(hWnd);
    snarlStruct.id       = replyMsg;
    if (appName.length() > SNARL_STRING_LENGTH) {
        strcpy(snarlStruct.title, (appName.substr(0, SNARL_STRING_LENGTH - 1)).c_str());
    } else {
        strcpy(snarlStruct.title, appName.c_str());
    }
    return bool(send(snarlStruct));
}

bool SnarlInterface::snRevokeConfig(HWND hWnd)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.cmd      = SNARL_REVOKE_CONFIG_WINDOW;
    snarlStruct.lngData2 = reinterpret_cast<long>(hWnd);
    return bool(send(snarlStruct));
}

bool SnarlInterface::snGetVersion(int *major, int *minor)
{
    SNARLSTRUCT snarlStruct;
    snarlStruct.cmd  = SNARL_GET_VERSION;
    long versionInfo = send(snarlStruct);
    if (versionInfo) {
        int maj = static_cast<int>(HIWORD(versionInfo));
        *major  = maj;
        int min = static_cast<int>(LOWORD(versionInfo));
        *minor  = min;
        return true;
    }
    return false;
}

long SnarlInterface::snGetGlobalMsg()
{
    std::wstring tmp;
    tmp = QString(SNARL_GLOBAL_MESSAGE.c_str()).toStdWString();
    return RegisterWindowMessage(tmp.c_str());
}

long SnarlInterface::send(SNARLSTRUCT snarlStruct)
{
    HWND hWnd = FindWindow(NULL, QString("Snarl").toStdWString().c_str());
    if (IsWindow(hWnd)) {
        COPYDATASTRUCT cds;
        cds.dwData = 2;
        cds.cbData = sizeof(snarlStruct);
        cds.lpData = &snarlStruct;
        LRESULT lr = SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cds);
        if (lr) {
            return lr;
        }
    }
    return 0;
}
