/**
 * FreeRDP: A Remote Desktop Protocol Implementation
 * RAIL Virtual Channel Plugin
 *
 * Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
 *
 * 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 FREERDP_CHANNEL_RAIL_SERVER_RAIL_H
#define FREERDP_CHANNEL_RAIL_SERVER_RAIL_H

#include <freerdp/api.h>
#include <freerdp/types.h>

#include <freerdp/rail.h>
#include <freerdp/channels/rail.h>

#ifdef __cplusplus
extern "C"
{
#endif

	typedef struct s_rail_server_context RailServerContext;
	typedef struct s_rail_server_private RailServerPrivate;

	typedef UINT (*psRailStart)(RailServerContext* context);
	typedef BOOL (*psRailStop)(RailServerContext* context);

	/* Client side callback types */
	typedef UINT (*psRailClientHandshake)(RailServerContext* context,
	                                      const RAIL_HANDSHAKE_ORDER* handshake);
	typedef UINT (*psRailClientClientStatus)(RailServerContext* context,
	                                         const RAIL_CLIENT_STATUS_ORDER* clientStatus);
	typedef UINT (*psRailClientExec)(RailServerContext* context, const RAIL_EXEC_ORDER* exec);
	typedef UINT (*psRailClientSysparam)(RailServerContext* context,
	                                     const RAIL_SYSPARAM_ORDER* sysparam);
	typedef UINT (*psRailClientActivate)(RailServerContext* context,
	                                     const RAIL_ACTIVATE_ORDER* activate);
	typedef UINT (*psRailClientSysmenu)(RailServerContext* context,
	                                    const RAIL_SYSMENU_ORDER* sysmenu);
	typedef UINT (*psRailClientSyscommand)(RailServerContext* context,
	                                       const RAIL_SYSCOMMAND_ORDER* syscommand);
	typedef UINT (*psRailClientNotifyEvent)(RailServerContext* context,
	                                        const RAIL_NOTIFY_EVENT_ORDER* notifyEvent);
	typedef UINT (*psRailClientGetAppidReq)(RailServerContext* context,
	                                        const RAIL_GET_APPID_REQ_ORDER* getAppidReq);
	typedef UINT (*psRailClientWindowMove)(RailServerContext* context,
	                                       const RAIL_WINDOW_MOVE_ORDER* windowMove);
	typedef UINT (*psRailClientSnapArrange)(RailServerContext* context,
	                                        const RAIL_SNAP_ARRANGE* snapArrange);
	typedef UINT (*psRailClientLangbarInfo)(RailServerContext* context,
	                                        const RAIL_LANGBAR_INFO_ORDER* langbarInfo);
	typedef UINT (*psRailClientLanguageImeInfo)(RailServerContext* context,
	                                            const RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo);
	typedef UINT (*psRailClientCompartmentInfo)(RailServerContext* context,
	                                            const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo);
	typedef UINT (*psRailClientCloak)(RailServerContext* context, const RAIL_CLOAK* cloak);
	typedef UINT (*psRailClientTextScale)(RailServerContext* context, UINT32 TextScale);
	typedef UINT (*psRailClientCaretBlinkRate)(RailServerContext* context, UINT32 CaretBlinkRate);

	/* Server side messages sending methods */
	typedef UINT (*psRailServerHandshake)(RailServerContext* context,
	                                      const RAIL_HANDSHAKE_ORDER* handshake);
	typedef UINT (*psRailServerHandshakeEx)(RailServerContext* context,
	                                        const RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
	typedef UINT (*psRailServerSysparam)(RailServerContext* context,
	                                     const RAIL_SYSPARAM_ORDER* sysparam);
	typedef UINT (*psRailServerLocalMoveSize)(RailServerContext* context,
	                                          const RAIL_LOCALMOVESIZE_ORDER* localMoveSize);
	typedef UINT (*psRailServerMinMaxInfo)(RailServerContext* context,
	                                       const RAIL_MINMAXINFO_ORDER* minMaxInfo);
	typedef UINT (*psRailServerTaskbarInfo)(RailServerContext* context,
	                                        const RAIL_TASKBAR_INFO_ORDER* taskbarInfo);
	typedef UINT (*psRailServerLangbarInfo)(RailServerContext* context,
	                                        const RAIL_LANGBAR_INFO_ORDER* langbarInfo);
	typedef UINT (*psRailServerExecResult)(RailServerContext* context,
	                                       const RAIL_EXEC_RESULT_ORDER* execResult);
	typedef UINT (*psRailServerGetAppidResp)(RailServerContext* context,
	                                         const RAIL_GET_APPID_RESP_ORDER* getAppIdResp);
	typedef UINT (*psRailServerZOrderSync)(RailServerContext* context,
	                                       const RAIL_ZORDER_SYNC* zOrderSync);
	typedef UINT (*psRailServerCloak)(RailServerContext* context, const RAIL_CLOAK* cloak);
	typedef UINT (*psRailServerPowerDisplayRequest)(
	    RailServerContext* context, const RAIL_POWER_DISPLAY_REQUEST* PowerDisplayRequest);
	typedef UINT (*psRailServerGetAppidRespEx)(RailServerContext* context,
	                                           const RAIL_GET_APPID_RESP_EX* GetAppidRespEx);

	struct s_rail_server_context
	{
		HANDLE vcm;
		void* custom;

		psRailStart Start;
		psRailStop Stop;

		/* Callbacks from client */
		psRailClientHandshake ClientHandshake;
		psRailClientClientStatus ClientClientStatus;
		psRailClientExec ClientExec;
		psRailClientSysparam ClientSysparam;
		psRailClientActivate ClientActivate;
		psRailClientSysmenu ClientSysmenu;
		psRailClientSyscommand ClientSyscommand;
		psRailClientNotifyEvent ClientNotifyEvent;
		psRailClientGetAppidReq ClientGetAppidReq;
		psRailClientWindowMove ClientWindowMove;
		psRailClientSnapArrange ClientSnapArrange;
		psRailClientLangbarInfo ClientLangbarInfo;
		psRailClientLanguageImeInfo ClientLanguageImeInfo;
		psRailClientCompartmentInfo ClientCompartmentInfo;
		psRailClientCloak ClientCloak;
		psRailClientTextScale ClientTextScale;
		psRailClientCaretBlinkRate ClientCaretBlinkRate;

		/* Methods for sending server side messages */
		psRailServerHandshake ServerHandshake;
		psRailServerHandshakeEx ServerHandshakeEx;
		psRailServerSysparam ServerSysparam;
		psRailServerLocalMoveSize ServerLocalMoveSize;
		psRailServerMinMaxInfo ServerMinMaxInfo;
		psRailServerTaskbarInfo ServerTaskbarInfo;
		psRailServerLangbarInfo ServerLangbarInfo;
		psRailServerExecResult ServerExecResult;
		psRailServerZOrderSync ServerZOrderSync;
		psRailServerCloak ServerCloak;
		psRailServerPowerDisplayRequest ServerPowerDisplayRequest;
		psRailServerGetAppidResp ServerGetAppidResp;
		psRailServerGetAppidRespEx ServerGetAppidRespEx;

		RailServerPrivate* priv;
		rdpContext* rdpcontext;
	};

	FREERDP_API void rail_server_context_free(RailServerContext* context);

	WINPR_ATTR_MALLOC(rail_server_context_free, 1)
	FREERDP_API RailServerContext* rail_server_context_new(HANDLE vcm);

	FREERDP_API UINT rail_server_handle_messages(RailServerContext* context);
	FREERDP_API void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags);

#ifdef __cplusplus
}
#endif

#endif /* FREERDP_CHANNEL_RAIL_SERVER_RAIL_H */
