/*
 * Copyright (C) 2020 Uniontech Technology Co., Ltd.
 *
 * Author:     xinbo wang <wangxinbo@uniontech.com>
 *
 * Maintainer: xinbo wang <wangxinbo@uniontech.com>
 *
 * 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 3 of the License, or
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <stdint.h>

#include <X11/Xlib.h>
#include <X11/Xlibint.h>

#include "uaceExt.h"
#include "displayController.h"

static Bool extensionInited = False;
static XExtCodes *codes = 0;

static Bool checkExtension(Display *dpy)
{
    if (!extensionInited) {
        extensionInited = True;
        codes = XInitExtension(dpy, UACE_EXTENSION_NAME);
        if (!codes)
            return False;
    }
    return codes != 0;
}

Bool XUaceExtQueryExtension(Display *dpy, int *event_basep, int *error_basep)
{
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    if (!info) {
        return False;
    }

    *event_basep = info->codes->first_event;
    *error_basep = info->codes->first_error;
    return True;
}

Bool XUaceExtSetProtectedWindow(Display* dpy, Window window)
{   
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    xUaceExtSetProtectedWindowReq *req;
    xUaceExtSetProtectedWindowReply rep;

    LockDisplay(dpy);
    GetReq(UaceExtSetProtectedWindow, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtSetProtectedWindow;
    req->window = window;

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }

    UnlockDisplay(dpy);
    SyncHandle();
    return rep.success;
}

Bool XUaceExtRegisterSelectionSpy(Display* dpy, int server_read_fd, int server_write_fd)
{   
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    xUaceExtRegisterSelectionSpyReq *req;
    xUaceExtRegisterSelectionReply rep;

    LockDisplay(dpy);
    GetReq(UaceExtRegisterSelectionSpy, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtRegisterSelectionSpy;
    req->readfd = server_read_fd;
    req->writefd = server_write_fd;

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }

    UnlockDisplay(dpy);
    SyncHandle();
    return rep.success;
}



Bool XUaceExtRemoveProtectedWindow(Display* dpy, Window window)
{
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    xUaceExtRemoveProtectedWindowReq *req;
    xUaceExtRemoveProtectedWindowReply rep;

    LockDisplay(dpy);
    GetReq(UaceExtRemoveProtectedWindow, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtRemoveProtectedWindow;
    req->window = window;

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }
    UnlockDisplay(dpy);
    SyncHandle();
    return rep.success;
}

int XUaceExtGetWindowPID(Display* dpy, Window window)
{
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    xUaceExtGetWindowPIDReq *req;
    xUaceExtGetWindowPIDReply rep;

    LockDisplay(dpy);
    GetReq(UaceExtGetWindowPID, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtGetWindowPID;
    req->window = window;

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }
    UnlockDisplay(dpy);
    SyncHandle();
    return rep.PID;
}

Bool XUaceExtSetScreenShotTools(Display* dpy,const char *name)
{
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    xUaceExtSetScreenShotToolsReq *req;
    xUaceExtSetScreenShotToolsReply rep;

    int paramLen = strlen(name);
    if (paramLen > 255) return False;

    LockDisplay(dpy);
    GetReq(UaceExtSetScreenShotTools, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtSetScreenShotTools;

    req->length += (paramLen + 3) >> 2;
    req->paramLen = paramLen;
    Data(dpy, name, paramLen);

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }

    UnlockDisplay(dpy);
    SyncHandle();
    return rep.success;
}

Bool XUaceExtRemoveScreenShotTools(Display* dpy, char *name)
{
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest)

    xUaceExtRemoveScreenShotToolsReq *req;
    xUaceExtRemoveScreenShotToolsReply rep;

    LockDisplay(dpy);
    GetReq(UaceExtRemoveScreenShotTools, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtRemoveScreenShotTools;
    req->name = name;

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }
    UnlockDisplay(dpy);
    SyncHandle();
    return rep.success;
}

Bool XUaceExtFreeScreenShotTools(Display* dpy)
{
    WIExtDisplayInfo *info = wi_find_display(dpy);
    WICheckExtension(info, BadRequest);

    xUaceExtFreeScreenShotToolsReq *req;
    xUaceExtFreeScreenShotToolsReply rep;

    LockDisplay(dpy);
    GetReq(UaceExtFreeScreenShotTools, req);
    req->reqType = info->codes->major_opcode;
    req->uaceReqType = X_UaceExtFreeScreenShotTools;

    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }
    UnlockDisplay(dpy);
    SyncHandle();
    return rep.success;
}