package com.dji.sdk.cloudapi.psdk.api;

import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromPsdk;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionToPsdkRequest;
import com.dji.sdk.cloudapi.interconnection.InterconnectionMethodEnum;
import com.dji.sdk.cloudapi.psdk.*;
import com.dji.sdk.config.version.GatewayManager;
import com.dji.sdk.mqtt.ChannelName;
import com.dji.sdk.mqtt.MqttReply;
import com.dji.sdk.mqtt.events.EventsDataRequest;
import com.dji.sdk.mqtt.events.TopicEventsRequest;
import com.dji.sdk.mqtt.events.TopicEventsResponse;
import com.dji.sdk.mqtt.services.ServicesPublish;
import com.dji.sdk.mqtt.services.ServicesReplyData;
import com.dji.sdk.mqtt.services.TopicServicesResponse;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.MessageHeaders;

import javax.annotation.Resource;

/**
 * Abstract PSDK service
 * Provides PSDK payload control and event handling capabilities
 * 
 * @author sean
 * @version 1.7
 * @date 2023/10/16
 */
public abstract class AbstractPsdkService {

    @Resource
    private ServicesPublish servicesPublish;

    // ==================== Events (Device to Cloud) ====================

    /**
     * Event notification of PSDK custom data transmission
     * @param request  data
     * @param headers  message headers
     * @return events_reply
     */
    @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_CUSTOM_DATA_TRANSMISSION_FROM_PSDK, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public TopicEventsResponse<MqttReply> customDataTransmissionFromPsdk(TopicEventsRequest<CustomDataTransmissionFromPsdk> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("customDataTransmissionFromPsdk not implemented");
    }

    /**
     * Event notification of PSDK UI resource upload result
     * @param request  data
     * @param headers  message headers
     * @return events_reply
     */
    @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_PSDK_UI_RESOURCE_UPLOAD_RESULT, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public TopicEventsResponse<MqttReply> psdkUiResourceUploadResult(TopicEventsRequest<PsdkUiResourceUploadResult> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("psdkUiResourceUploadResult not implemented");
    }

    /**
     * Event notification of PSDK floating window text
     * @param request  data
     * @param headers  message headers
     * @return events_reply
     */
    @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_PSDK_FLOATING_WINDOW_TEXT, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public TopicEventsResponse<MqttReply> psdkFloatingWindowText(TopicEventsRequest<PsdkFloatingWindowText> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("psdkFloatingWindowText not implemented");
    }

    /**
     * Event notification of speaker audio play progress
     * @param request  data
     * @param headers  message headers
     * @return events_reply
     */
    @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_SPEAKER_AUDIO_PLAY_START_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public TopicEventsResponse<MqttReply> speakerAudioPlayStartProgress(TopicEventsRequest<EventsDataRequest<SpeakerAudioPlayStartProgress>> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("speakerAudioPlayStartProgress not implemented");
    }

    /**
     * Event notification of speaker TTS play progress
     * @param request  data
     * @param headers  message headers
     * @return events_reply
     */
    @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_SPEAKER_TTS_PLAY_START_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public TopicEventsResponse<MqttReply> speakerTtsPlayStartProgress(TopicEventsRequest<EventsDataRequest<SpeakerTtsPlayStartProgress>> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("speakerTtsPlayStartProgress not implemented");
    }

    // ==================== Services (Cloud to Device) ====================

    /**
     * Send custom data to PSDK payload
     * @param gateway  gateway manager
     * @param request  custom data (max 256 bytes)
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> customDataTransmissionToPsdk(GatewayManager gateway, CustomDataTransmissionToPsdkRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                InterconnectionMethodEnum.CUSTOM_DATA_TRANSMISSION_TO_PSDK.getMethod(),
                request);
    }

    /**
     * Set PSDK widget value
     * @param gateway  gateway manager
     * @param request  widget value set request
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> psdkWidgetValueSet(GatewayManager gateway, PsdkWidgetValueSetRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.WIDGET_VALUE_SET.getMethod(),
                request);
    }

    /**
     * Set PSDK input box text
     * @param gateway  gateway manager
     * @param request  input box text set request (max 128 bytes)
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> psdkInputBoxTextSet(GatewayManager gateway, PsdkInputBoxTextSetRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.INPUT_BOX_TEXT_SET.getMethod(),
                request);
    }

    /**
     * Start playing audio on speaker
     * @param gateway  gateway manager
     * @param request  audio play start request
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> speakerAudioPlayStart(GatewayManager gateway, SpeakerAudioPlayStartRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.SPEAKER_AUDIO_PLAY_START.getMethod(),
                request);
    }

    /**
     * Start playing TTS on speaker
     * @param gateway  gateway manager
     * @param request  TTS play start request
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> speakerTtsPlayStart(GatewayManager gateway, SpeakerTtsPlayStartRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.SPEAKER_TTS_PLAY_START.getMethod(),
                request);
    }

    /**
     * Replay the last audio/TTS on speaker
     * @param gateway  gateway manager
     * @param request  replay request
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> speakerReplay(GatewayManager gateway, SpeakerReplayRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.SPEAKER_REPLAY.getMethod(),
                request);
    }

    /**
     * Stop playing on speaker
     * @param gateway  gateway manager
     * @param request  play stop request
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> speakerPlayStop(GatewayManager gateway, SpeakerPlayStopRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.SPEAKER_PLAY_STOP.getMethod(),
                request);
    }

    /**
     * Set speaker play mode
     * @param gateway  gateway manager
     * @param request  play mode set request (0: single, 1: loop)
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> speakerPlayModeSet(GatewayManager gateway, SpeakerPlayModeSetRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.SPEAKER_PLAY_MODE_SET.getMethod(),
                request);
    }

    /**
     * Set speaker play volume
     * @param gateway  gateway manager
     * @param request  play volume set request (0-100)
     * @return services_reply
     */
    public TopicServicesResponse<ServicesReplyData> speakerPlayVolumeSet(GatewayManager gateway, SpeakerPlayVolumeSetRequest request) {
        return servicesPublish.publish(
                gateway.getGatewaySn(),
                PsdkMethodEnum.SPEAKER_PLAY_VOLUME_SET.getMethod(),
                request);
    }
}
