//
//  Copyright © 2017 IPsoft. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "IPSAKObject.h"
NS_ASSUME_NONNULL_BEGIN

@class IPSAKFormInputData;
@class IPSAKPresentingResource;
@class IPSAKRequestingResource;
@class IPSAKBpnExecutionEvent;
/**
 Constants indicating the type of message received from Amelia.
 */
typedef NS_ENUM(NSInteger, IPSAKMessageType) {
    /**
     Message type not yet handled by the SDK. See `messageTypeString` to get the underlying message type.
     */
    IPSAKMessageTypeUnknown,
    /**
     An echo of a user response. Used to populate the user side of a chat.
     */
    IPSAKMessageTypeOutboundEcho,
    /**
     A message Amelia sends. This is typically the type of message you want to echo into your chat UI.
     
     This message may have a formInputData attribute, which can be used to construct custom form widgets.
     */
    IPSAKMessageTypeOutboundText,
    /**
     A message Amelia send when it encounters an unexpected error in the pipeline. This is typically the type of message you want to echo into your chat UI.
     */
    IPSAKMessageTypeOutboundFinalError,
    /**
     A message Amelia sends when it is in the middle of a process. This is typically the type of message you want to echo into your chat UI. It will most often not have X-Amelia-Input-Enabled set to 'true', as most UIs will want to keep the input disabled until Amelia has concluded its process.
     */
    IPSAKMessageTypeOutboundProgressText,
    /**
     The Amelia avatar has made a voice change. As the speech is not yet implemented this message can be ignored.
     */
    IPSAKMessageTypeOutboundAvatarChangeVoice,
    /**
     An escalation is in progress.
     */
    IPSAKMessageTypeOutboundEscalationStarted,
    /**
     A message Amelia sends to request acknowledgment from the client that it is still there. It typically contains no messageText, so is not useful for updating the chat box directly. AmeliaChat will send responses automatically to preserve the conversation, but after the configured idle wait time it will also notify Amelia that the user has gone idle. Typically, the automated responses are enough, though you may listen to this event if you need another portion of your UI to respond to an ack request
     */
    IPSAKMessageTypeOutboundAckRequest,
    /**
     A message Amelia sends when the user session is closed. It will contain some messageText, so you may use it to update the chat box as well as to inform other components of your UI that the session has terminated.
     */
    IPSAKMessageTypeOutboundSessionClosed,
    /**
     Amelia has closed the conversation.
     */
    IPSAKMessageTypeOutboundConversationClosed,
    /**
     A social message Amelia could send if it detects the user is idle.
     */
    IPSAKMessageTypeOutboundIdleTalk,
    /**
     A message Amelia sends when it detects the user is idle, but has no social messages configured. This will not have any messageText, so it is typically not useful to update the chat window itself, though a UI can listen for this event to detect when the user has gone into an idle state.
     */
    IPSAKMessageTypeOutboundNoIdleTalk,
    /**
     A message containing section widgets for working with another system.
     */
    IPSAKMessageTypeOutboundIntegration,
    /**
     A message Amelia sends when the agent has changed, normally when someone has picked up the conversation.
     */
    IPSAKMessageTypeOutboundAgentSessionChanged,
    /**
     A message Amelia sends after an agent has picked up a session, indicating that all messages have been replayed. Not necessary to handle.
     */
    IPSAKMessageTypeOutboundReplayFinished,
    /**
     WolframAlphaFinalMessage will fire when Amelia says text at the conclusion of a request made to WolframAlpha. This is typically the type of message you want to echo into your chat UI.
     */
    IPSAKMessageTypeOutboundWolframAlphaFinal,
    /**
     A message Amelia sends when she should send a resource to the client. This message contains all the information which can be used to retrieve the resource.
     */
    IPSAKMessageTypeOutboundPresentMessage,
    /**
     A message Amelia sends that includes a form for user to fill out.
     */
    IPSAKMessageTypeOutboundFormInputMessage,
    /**
     A message Amelia sends to request a resource(file) from user
     */
    IPSAKMessageTypeOutboundRequestMessage,
    /**
     A BPN event of actions happen with a process or task.
     */
    IPSAKMessageTypeOutboundBpnExecutionMessage,
    /**
     Amelia is ready to take user input
     */
    IPSAKMessageTypeOutboundAmeliaReadyMessage
};

/**
 Values representing Amelia's mood.
 NEUTRAL, HAPPY, SAD, SURPRISED, ANGRY, DISGUSTED, FEAR, CONTEMPT
 */
typedef NS_ENUM(NSInteger, IPSAKMoodType) {
    /// Mood attribute was not present in the message
    IPSAKMoodNoMood,
    /// Amelia is neutral.
    IPSAKMoodNeutral,
    /// Amelia is happy.
    IPSAKMoodHappy,
    /// Amelia is sad.
    IPSAKMoodSad,
    /// Amelia is surprised.
    IPSAKMoodSurprised,
    /// Amelia is angry.
    IPSAKMoodAngry,
    /// Amelia is disgusted.
    IPSAKMoodDisgusted,
    /// Amelia is afraid.
    IPSAKMoodFear,
    /// Amelia feels contempt.
    IPSAKMoodContempt,
    /// The mood could not be mapped to the enum. See `moodString`.
    IPSAKMoodUnknown,
};

/**
 The `IPSAKMessage` class represents a messages received from Amelia.
 
 Which properties are set depends on the type of message, but `messageType` (and `messageTypeString`) are always set.
 */
@interface IPSAKMessage : NSObject

/**
 Create a message from the supplied json and stomp headers.
 
 @note The returned instance can also be of type `IPSAKDownloadMessage`
 
 @param body A dictionary object with the properties of the message.
 @param headers A list of Stomp headers.
 @param error An `NSError` object if a message could not be created.
 */
+ (instancetype _Nullable)messageWithBody:(NSDictionary *)body
                                  headers:(NSDictionary<NSString *, NSString *> *_Nullable)headers
                                    error:(NSError **_Nullable)error;
/**
 The message text.
 */
@property (nullable, nonatomic, copy, readonly) NSString *messageText;
/**
 Hint text.
 */
@property (nullable, nonatomic, copy, readonly) NSString *hintText;
/**
 meta data of resource to present
 */
@property (nonatomic, copy,readonly) IPSAKPresentingResource * presentingMetaData;
/**
 meta data of resource to request
*/
@property (nonatomic, copy,readonly) IPSAKRequestingResource * requestingMetaData;
/**
 Indicates whether requesting resource can be multiple files
 */
@property (nonatomic,assign,readonly) BOOL multiple;
/**
 Indicates whether resource requesting operation can be cancelled
 */
@property (nonatomic,assign,readonly) BOOL cancellable;
/**
 The name of the user who sent the message.
 */
@property (nullable, nonatomic, copy, readonly) NSString *fromUserDisplayName;

/**
 The type of message.
 
 @note If `messageType == IPSAKMessageTypeUnknown` the message type could not be mapped to the enum and the mood type text can be obtained from `moodTypeString`.
 */
@property (nonatomic, readonly) IPSAKMessageType messageType;
/**
 The text represenation of the message type.
 */
@property (nonatomic, copy, readonly) NSString *messageTypeString;

/**
 Amelia's mood for the current message. 
 
 @note If `mood == IPSAKMoodNoMood` it indicates that Amelia's mood has not changed.
 
 @note If `mood == IPSAKMoodUnknown` the mood could not be mapped to the enum and the mood text can be obtained from `moodString`.
 */
@property (nonatomic, readonly) IPSAKMoodType mood;
/**
 The text representation of the mood.
 */
@property (nullable, nonatomic, copy, readonly) NSString *moodString;

/**
 Whether the message is a self echo from the user or not.
 */
@property (nonatomic, readonly) BOOL selfEcho;

/**
 Whether user response to this should be secured.
 */
@property (nonatomic, readonly) BOOL toSecureResponse;

/**
 The id of the conversation this message belongs to.
 */
@property (nonatomic,copy,readonly) NSString *conversationId;
/**
 This message is a response to an earlier message. See `messageId`.
 */
@property (nonatomic, readonly) NSInteger inResponseToMessageId;
/**
 The id of session this message belongs to.
 */
@property (nonatomic, readonly) NSInteger sourceSessionId;
/**
 The id of this message.
 */
@property (nonatomic, readonly) NSInteger messageId;

/**
 The contents of the field formInputData.
 */
@property (nullable, nonatomic, copy, readonly) IPSAKFormInputData *formInputData;

/**
 The contents of the field integrationMessageData.
 */
@property (nullable, nonatomic, copy, readonly) NSDictionary *integrationMessageData;

/**
 The voice used by the Amelia avatar. Only set when `messageType == IPSAKMessageTypeOutboundAvatarChangeVoice`
 */
@property (nullable, nonatomic, copy, readonly) NSString *avatarVoice;

/**
 List of text that should be spoken.
 */
@property (nullable, nonatomic, copy, readonly) NSArray<NSString *> *textsToSpeak;

/**
 The Stomp headers included in the message.
 */
@property (nullable, nonatomic, copy, readonly) NSDictionary<NSString *, NSString *> *headers;
/**
 details about bpn execution. Only available with OutboundBpnExecutionEventMessage
 */
@property (nonatomic, copy,readonly) IPSAKBpnExecutionEvent *bpnExecutionEvent;

@end

NS_ASSUME_NONNULL_END
