/*
 * Copyright (c) 2023-2026 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef COOPERATE_EVENTS_H
#define COOPERATE_EVENTS_H

#include <future>
#include <string>
#include <variant>
#include <set>

#include "coordination_message.h"
#include "i_cooperate.h"
#include "i_device.h"

namespace OHOS {
namespace Msdp {
namespace DeviceStatus {
namespace Cooperate {
enum CooperateState : size_t {
    COOPERATE_STATE_FREE = 0,
    COOPERATE_STATE_OUT,
    COOPERATE_STATE_IN,
    N_COOPERATE_STATES,
};

enum class CooperateEventType {
    NOOP,
    QUIT,
    ADD_OBSERVER,
    REMOVE_OBSERVER,
    REGISTER_LISTENER,
    UNREGISTER_LISTENER,
    REGISTER_HOTAREA_LISTENER,
    UNREGISTER_HOTAREA_LISTENER,
    ENABLE,
    DISABLE,
    START,
    WITH_OPTIONS_START,
    STOP,
    GET_COOPERATE_STATE,
    REGISTER_EVENT_LISTENER,
    UNREGISTER_EVENT_LISTENER,
    UPDATE_COOPERATE_FLAG,
    SET_DAMPLING_COEFFICIENT,
    DUMP,
    APP_CLOSED,
    DDM_BOARD_ONLINE,
    DDM_BOARD_OFFLINE,
    DDP_COOPERATE_SWITCH_CHANGED,
    INPUT_HOTPLUG_EVENT,
    INPUT_POINTER_EVENT,
    DSOFTBUS_SESSION_OPENED,
    DSOFTBUS_SESSION_CLOSED,
    DSOFTBUS_START_COOPERATE,
    DSOFTBUS_COME_BACK,
    DSOFTBUS_STOP_COOPERATE,
    DSOFTBUS_RELAY_COOPERATE,
    DSOFTBUS_RELAY_COOPERATE_FINISHED,
    DSOFTBUS_SUBSCRIBE_MOUSE_LOCATION,
    DSOFTBUS_UNSUBSCRIBE_MOUSE_LOCATION,
    DSOFTBUS_REPLY_SUBSCRIBE_MOUSE_LOCATION,
    DSOFTBUS_REPLY_UNSUBSCRIBE_MOUSE_LOCATION,
    DSOFTBUS_MOUSE_LOCATION,
    DSOFTBUS_INPUT_DEV_SYNC,
    DSOFTBUS_INPUT_DEV_HOT_PLUG,
    UPDATE_VIRTUAL_DEV_ID_MAP,
    DSOFTBUS_COME_BACK_WITH_OPTIONS,
    DSOFTBUS_COOPERATE_WITH_OPTIONS,
    DSOFTBUS_RELAY_COOPERATE_WITHOPTIONS,
    DSOFTBUS_RELAY_COOPERATE_WITHOPTIONS_FINISHED,
    STOP_ABOUT_VIRTUALTRACKPAD
};

struct Rectangle {
    int32_t width;
    int32_t height;
    int32_t x;
    int32_t y;
};

struct AddObserverEvent {
    std::shared_ptr<ICooperateObserver> observer;
};
using RemoveObserverEvent = AddObserverEvent;

struct RegisterListenerEvent {
    int32_t pid;
    int32_t userData;
};

using UnregisterListenerEvent = RegisterListenerEvent;
using RegisterHotareaListenerEvent = RegisterListenerEvent;
using UnregisterHotareaListenerEvent = RegisterListenerEvent;
using DisableCooperateEvent = RegisterListenerEvent;

struct StartCooperateEvent {
    int32_t pid;
    int32_t userData;
    std::string remoteNetworkId;
    int32_t startDeviceId;
    std::shared_ptr<std::promise<int32_t>> errCode;
    int32_t uid { 0 };
    int32_t userId { -1 };
    std::string accountId;
    bool needCheckSameAccount { true };
};

struct EnableCooperateEvent {
    int32_t tokenId;
    int32_t pid;
    int32_t userData;
};

struct ClientDiedEvent {
    int32_t pid;
};

struct StopCooperateEvent {
    int32_t pid;
    int32_t userData;
    bool isUnchained;
    std::string networkId;
};

struct GetCooperateStateEvent {
    int32_t pid;
    int32_t userData;
    std::string networkId;
};

struct RegisterEventListenerEvent {
    int32_t pid;
    std::string networkId;
};
using UnregisterEventListenerEvent = RegisterEventListenerEvent;

struct DumpEvent {
    int32_t fd;
};

struct DDMBoardOnlineEvent {
    std::string networkId;
    bool normal;
    int32_t errCode { static_cast<int32_t>(CoordinationErrCode::COORDINATION_OK) };
};

struct StatusChangeEvent {
    std::string networkId;
    CoordinationMessage msg { CoordinationMessage::UNKNOW };
};

using DDMBoardOfflineEvent = DDMBoardOnlineEvent;
using DDPCooperateSwitchChanged = DDMBoardOnlineEvent;

enum class InputHotplugType {
    PLUG,
    UNPLUG,
};

struct InputHotplugEvent {
    int32_t deviceId;
    InputHotplugType type;
    bool isKeyboard { false };
};

struct InputPointerEvent {
    int32_t deviceId;
    int32_t pointerAction;
    int32_t sourceType;
    Coordinate position;
    int32_t currentDisplayId { 0 };
    std::set<int32_t> pressedButtons;
};

using DSoftbusSessionOpened = DDMBoardOnlineEvent;
using DSoftbusSessionClosed = DDMBoardOnlineEvent;

struct DSoftbusStartCooperate {
    std::string networkId;
    std::string originNetworkId;
    bool success;
    NormalizedCoordinate cursorPos;
    StartCooperateData extra;
    int32_t errCode { static_cast<int32_t>(CoordinationErrCode::COORDINATION_OK) };
    int32_t pointerSpeed { -1 };
    int32_t touchPadSpeed { -1 };
    int32_t uid { 0 };
    int32_t userId { -1 };
    std::string accountId;
    bool needCheckSameAccount { true };
};

struct DSoftbusCooperateOptions {
    std::string networkId;
    std::string originNetworkId;
    bool success;
    NormalizedCooperateOptions cooperateOptions;
    StartCooperateData extra;
    int32_t errCode { static_cast<int32_t>(CoordinationErrCode::COORDINATION_OK) };
    int32_t pointerSpeed { -1 };
    int32_t touchPadSpeed { -1 };
    int32_t userId { -1 };
    std::string accountId;
    bool needCheckSameAccount { true };
};

using DSoftbusStartCooperateFinished = DSoftbusStartCooperate;
using DSoftbusComeBack = DSoftbusStartCooperate;
using DSoftbusStopCooperate = DDMBoardOnlineEvent;
using DSoftbusStopCooperateFinished = DDMBoardOnlineEvent;
using DSoftbusCooperateWithOptionsFinished = DSoftbusCooperateOptions;
using DSoftbusComeBackWithOptions = DSoftbusCooperateOptions;

struct DSoftbusRelayCooperate {
    std::string networkId;
    std::string targetNetworkId;
    bool normal;
    int32_t pointerSpeed { -1 };
    int32_t touchPadSpeed { -1 };
    int32_t uid { 0 };
    int32_t userId { -1 };
    std::string accountId;
    bool needCheckSameAccount { true };
};

struct DSoftbusSubscribeMouseLocation {
    std::string networkId;
    std::string remoteNetworkId;
};

struct DSoftbusReplySubscribeMouseLocation {
    std::string networkId;
    std::string remoteNetworkId;
    bool result { false };
};

struct LocationInfo {
    int32_t displayX;
    int32_t displayY;
    int32_t displayWidth;
    int32_t displayHeight;
};
struct DSoftbusSyncMouseLocation {
    std::string networkId;
    std::string remoteNetworkId;
    LocationInfo mouseLocation;
};

struct DSoftbusSyncInputDevice {
    std::string networkId;
    std::vector<std::shared_ptr<IDevice>> devices;
};

struct DSoftbusHotPlugEvent {
    std::string networkId;
    InputHotplugType type;
    std::shared_ptr<IDevice> device;
};

struct NotAllowCooperateWhenMotionDragging {
    int32_t pid;
    int32_t userData;
    std::string networkId;
    bool success;
    int32_t errCode { static_cast<int32_t>(CoordinationErrCode::COORDINATION_OK) };
};

using DSoftbusReplyUnSubscribeMouseLocation = DSoftbusReplySubscribeMouseLocation;
using DSoftbusUnSubscribeMouseLocation = DSoftbusSubscribeMouseLocation;

using DSoftbusRelayCooperateFinished = DSoftbusRelayCooperate;

struct UpdateCooperateFlagEvent {
    uint32_t mask;
    uint32_t flag;
};

struct SetDamplingCoefficientEvent {
    uint32_t direction;
    double coefficient;
};

struct UpdateVirtualDeviceIdMapEvent {
    std::unordered_map<int32_t, int32_t> remote2VirtualIds;
};

struct StartWithOptionsEvent {
    int32_t pid { -1 };
    int32_t userData { 0 };
    std::string remoteNetworkId;
    int32_t startDeviceId { -1 };
    int32_t displayX { -1 };
    int32_t displayY { -1 };
    int32_t displayId { -1 };
    std::shared_ptr<std::promise<int32_t>> errCode;
    int32_t userId { -1 };
    std::string accountId;
    bool needCheckSameAccount { true };
};

struct CooperateEvent {
    CooperateEvent() : type(CooperateEventType::QUIT) {}

    explicit CooperateEvent(CooperateEventType ty) : type(ty) {}

    template<typename Event>
    CooperateEvent(CooperateEventType ty, Event ev) : type(ty), event(ev) {}

    CooperateEventType type;
    std::variant<
        AddObserverEvent,
        RegisterListenerEvent,
        StartCooperateEvent,
        StopCooperateEvent,
        EnableCooperateEvent,
        GetCooperateStateEvent,
        RegisterEventListenerEvent,
        DSoftbusSubscribeMouseLocation,
        DSoftbusReplySubscribeMouseLocation,
        DSoftbusSyncMouseLocation,
        DumpEvent,
        DDMBoardOnlineEvent,
        InputHotplugEvent,
        InputPointerEvent,
        DSoftbusStartCooperate,
        DSoftbusRelayCooperate,
        ClientDiedEvent,
        UpdateCooperateFlagEvent,
        SetDamplingCoefficientEvent,
        DSoftbusSyncInputDevice,
        DSoftbusHotPlugEvent,
        UpdateVirtualDeviceIdMapEvent,
        StartWithOptionsEvent,
        DSoftbusCooperateOptions,
        NotAllowCooperateWhenMotionDragging
    > event;
};

inline constexpr int32_t DEFAULT_TIMEOUT { 5000 };
inline constexpr int32_t REPEAT_ONCE { 1 };
inline constexpr int32_t DEFAULT_COOLING_TIME { 10 };
inline constexpr int32_t POINTER_EVENT_TIMEOUT { 10000 };
inline constexpr int32_t SCREEN_LOCKED_TIMEOUT { 600000 };
} // namespace Cooperate
} // namespace DeviceStatus
} // namespace Msdp
} // namespace OHOS
#endif // COOPERATE_EVENTS_H