/*
 * Copyright (C) 2024 Uniontech Technology Co., Ltd.
 *
 * Author:     liuzheng <liuzheng@uniontech.com>
 *
 * Maintainer: liuzheng <liuzheng@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 "displayjack_clipboard.h"
#include "systemclipboard.h"
#include "datamanage/clipdata.h"
#include "datamanage/clipdataproperty.h"
#include "datamanage/clipdatarecord.h"
#include "clipboarddataprocess.h"

// #include <QObject>
#include <assert.h>
#include <string.h>
#include <stdio.h>

ClipHandlePtr pClipHandle;

/**
 * @brief init_clip_board 初始化剪切板
 * @param path 数据存储和加载目录
 * @return 无
 */
int init_clipboard(const char *path)
{
    pClipHandle = (ClipHandlePtr)malloc(sizeof(ClipHandle));
    memset(pClipHandle, 0, sizeof(ClipHandle));

    if (!pClipHandle) {
        return -1;
    }

    if (!pClipHandle->xdgSessionType) {
        pClipHandle->xdgSessionType = getenv("XDG_SESSION_TYPE");
        pClipHandle->isWayland = (pClipHandle->xdgSessionType && strcmp(pClipHandle->xdgSessionType, "wayland") == 0);
    }
    if (!pClipHandle->isWayland) {
        destroy_clipboard();
        return -1;
    }

    if (strlen(path) == 0) {
        pClipHandle->pathDir = "/tmp";
    } else {
        int len = strlen(path) + 1;
        pClipHandle->pathDir = (char *)malloc(len);
        memset(pClipHandle->pathDir, 0, len);
        memcpy(pClipHandle->pathDir, path, len - 1);
    }
    SystemClipboard::getInstance().init();
    vector<string> filelist;
    ClipboardDataProcess::delete_non_list_files(ClipboardDataProcess::getClipboardDir(cachedataDir), filelist);
    return 0;
}

/**
 * @brief destroy_clipboard 销毁剪贴板
 * @param 无
 * @return 无
 */
void destroy_clipboard()
{
    if (!pClipHandle) {
        return;
    }
    free(pClipHandle);
    pClipHandle = NULL;
    SystemClipboard::getInstance().destroyData();
}

/**
 * @brief load_clipdata 加载剪贴板数据
 * @param 无
 * @return 无
 */
int load_clipdata()
{
    return SystemClipboard::getInstance().loadClipData();
}

/**
 * @brief get_clipboard_data_property_at 获取剪贴板数据属性
 * @param clipIndex 剪切板数据索引
 * @return 剪切板属性数据
 */
ClipboardDataProperty get_clipboard_data_property_at(int clipIndex)
{
    // todo
    ClipboardDataProperty vClipboardDataProperty;
    ClipData *vClipData = SystemClipboard::getInstance().getClipDataAt(clipIndex);
    if (vClipData) {
        ClipDataProperty *vClipDataProperty = vClipData->getProperty();
        if (vClipDataProperty)
            ClipboardDataProcess::convertClipPropertyData(vClipDataProperty, &vClipboardDataProperty, vClipData->getName());
    }

    return vClipboardDataProperty;
}

/**
 * @brief get_clipdata_count 获取剪贴板数据数量
 * @param 无
 * @return 剪切板数目
 */
int get_clipdata_count()
{
    return SystemClipboard::getInstance().getClipDataCount();
}

void remove_cilpboard_at(int clipIndex)
{
    SystemClipboard::getInstance().removeAt(clipIndex);
}

/**
 * @brief remove_cilpboard_at 根据索引移除剪贴板数据
 * @param clipIndex 剪切板索引
 * @return 无
 */
int move_cilpboard_at(int sourceClipIndex, int targetClipIndex)
{
    SystemClipboard::getInstance().moveAt(sourceClipIndex, targetClipIndex);
    return 1;
}

/**
 * @brief cilpboard_clear 清空剪贴板
 * @param 无
 * @return 无
 */
void cilpboard_clear()
{
    SystemClipboard::getInstance().clear();
}

/**
 * @brief get_clipboard_data_record_at 获取剪贴板数据记录
 * @param clipIndex 剪切板数据索引
 * @param dataIndex 剪切板数据记录索引
 * @return 剪切板实际数据
 */
ClipboardDataRecord get_clipboard_data_record_at(int clipIndex, int dataIndex)
{
    // todo
    ClipboardDataRecord vClipboardDataRecord;
    ClipData *vClipData = SystemClipboard::getInstance().getClipDataAt(clipIndex);
    if (vClipData) {
        ClipDataRecord *vClipDataRecord = vClipData->getRecordAt(dataIndex);
        if (vClipDataRecord)
            ClipboardDataProcess::convertClipRecordData(vClipDataRecord, &vClipboardDataRecord);
    }
    return vClipboardDataRecord;
}

/**
 * @brief get_clipboard_data_record_count 获取剪贴板数据记录数量
 * @param clipIndex 剪切板数据索引
 * @return 剪切板数据条目
 */
int get_clipboard_data_record_count(int clipIndex)
{
    if (SystemClipboard::getInstance().getClipDataAt(clipIndex) != nullptr)
        return SystemClipboard::getInstance().getClipDataAt(clipIndex)->getRecordCount();
    return -1;
}

/**
 * @brief remove_clipboard_data_record_at 移除剪贴板数据记录
 * @param clipIndex 剪切板数据索引
 * @param dataIndex 剪切板数据记录索引
 * @return 无
 */
void remove_clipboard_data_record_at(int clipIndex, int dataIndex)
{
    if (SystemClipboard::getInstance().getClipDataAt(clipIndex) != nullptr)
        SystemClipboard::getInstance().getClipDataAt(clipIndex)->removeRecordAt(dataIndex);
}

/**
 * @brief add_clipboard_data 添加剪贴板数据
 * @param propety 属性数据
 * @param record 记录数据
 * @return 无
 */
void add_clipboard_data(ClipboardDataProperty &propety, ClipboardDataRecord &record)
{
}

/**
 * @brief do_clipdata_add_listener_callback 添加剪贴板数据监听回调
 * @param func 回调函数地址
 * @param data 对象
 * @return 无
 */
void do_clipdata_add_listener_callback(ClipDataAddListenerPtr func, void *data)
{
    pClipHandle->ClipDataAddListener = func;
    pClipHandle->addUserData = data;
}

/**
 * @brief init_clipboard_connect 初始化剪贴板连接
 * @param path 无
 * @return 无
 * @note 此函数如果调用了LoadClipData函数可不调用此函数
 */
void init_clipboard_connect()
{
    SystemClipboard::getInstance().initConnect();
}

/**
 * @brief get_clip_index_by_name 根据名称获取剪贴板索引
 * @param name 剪切板数据名字
 * @return 索引
 */
int get_clip_index_by_name(const char *name)
{
    return SystemClipboard::getInstance().getClipIndexByName(string(name));
}

/**
 * @brief set_clip_on_top 设置剪贴板置顶
 * @param index 索引
 * @return 无
 */
void set_clip_on_top(int index)
{
    int clipindex = SystemClipboard::getInstance().setDataTop(index);
    if (clipindex != -1) {
        ClipData *vClip = SystemClipboard::getInstance().getClipDataAt(clipindex);
        if (vClip == NULL)
            return;
        // WaylandClip_Set_Selection(clip);
        vClip->getProperty()->setTimestamp(ClipboardDataProcess::getCurrentTime());
        SystemClipboard::getInstance().setDataToClipboard(vClip);
        SystemClipboard::getInstance().dataAddProcess(clipindex);
    }
}

/**
 * @brief set_clipboard_num 设置剪贴板数据数目
 * @param num 数目
 * @return 无
 */
void set_clipboard_num(int num)
{
    SystemClipboard::getInstance().setClipNum(num);
}

/**
 * @brief do_clipdata_delete_listener_callback 移除剪贴板数据监听回调
 * @param func 回调函数地址
 * @param data 对象
 * @return 无
 */
void do_clipdata_delete_listener_callback(ClipDataDeleteListenerPtr func, void *data)
{
    pClipHandle->ClipDataDeleteListener = func;
    pClipHandle->deleteUserData = data;
}

/**
 * @brief do_clipdata_state_listener_callback 数据传输状态监听回调
 * @param func 回调函数地址
 * @param data 对象
 * @return 无
 */
void do_clipdata_state_listener_callback(ClipDataStateListenerPtr func, void *data)
{
    pClipHandle->ClipDataStateListener = func;
    pClipHandle->stateUserData = data;
}

ClipDataRecordInfo get_clipboard_data_record_info_at(int clipIndex, int dataIndex)
{
    ClipDataRecordInfo info;
    ClipData *vClipData = SystemClipboard::getInstance().getClipDataAt(clipIndex);
    if (vClipData) {
        ClipDataRecord *vClipDataRecord = vClipData->getRecordAt(dataIndex);
        if (vClipDataRecord) {
            datafile_header vHead = ClipboardDataProcess::getDataHead(vClipDataRecord->getDataPath().c_str());
            info.vWidth = vHead.width;
            info.vHeight = vHead.height;
            info.vUrls = vClipDataRecord->getUrls();
            info.vDataPath = vClipDataRecord->getDataPath();
            info.vMimeType = vClipDataRecord->getMimeType();
            info.vDataType = vClipDataRecord->getDataType();
            info.bufferSize = vHead.size;
            info.vSmallData = NULL;
            info.len = 0;
            char *vSmallData = vClipDataRecord->getData(info.len);
            if (info.len > 0) {
                info.vSmallData = (char *)malloc(info.len);
            }
            memcpy(info.vSmallData, vSmallData, info.len); // 拷贝数据类型
        }
    }
    return info;
}

ClipDataPropertyInfo get_clipboard_data_property_info_at(int clipIndex)
{
    ClipDataPropertyInfo info;
    ClipData *vClipData = SystemClipboard::getInstance().getClipDataAt(clipIndex);
    if (vClipData) {
        ClipDataProperty *vClipDataProperty = vClipData->getProperty();
        info.vMimeTypes = vClipData->getMimeTypes();
        info.name = vClipData->getName();
        if (vClipDataProperty) {
            info.vTimestamp = vClipDataProperty->getTimestamp();
        }
    }
    return info;
}
