/*---------------------------------------------------------------------------*/
/* IntentHandler.m                                                           */
/* copyright (c) innovaphone 2015                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#import "IntentHandler.h"

@interface IntentHandler () <INStartCallIntentHandling, INStartAudioCallIntentHandling, INStartVideoCallIntentHandling, INSearchCallHistoryIntentHandling, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling>

@end

@implementation IntentHandler

- (id) handlerForIntent:(INIntent *)intent
{
    // This is the default implementation.  If you want different objects to handle different intents,
    // you can override this and return the handler you want for that particular intent.
    return self;
}

#pragma mark - INStartCallIntentHandling

-  (void) resolveCallCapabilityForStartCall:(INStartCallIntent *)intent withCompletion:(void (^)(INStartCallCallCapabilityResolutionResult *resolutionResult))completion
{
    completion([INStartCallCallCapabilityResolutionResult successWithResolvedCallCapability:intent.callCapability]);
}

- (void) resolveDestinationTypeForStartCall:(INStartCallIntent *)intent withCompletion:(void (^)(INCallDestinationTypeResolutionResult *resolutionResult))completion
{
    completion([INCallDestinationTypeResolutionResult successWithResolvedCallDestinationType:INCallDestinationTypeNormal]);
}

- (void) resolveCallRecordToCallBackForStartCall:(INStartCallIntent *)intent withCompletion:(void (^)(INCallRecordResolutionResult *resolutionResult))completion
{
    int i;
    NSMutableArray<INCallRecord *> *records = [NSMutableArray array];

    for (i = 0; i < intent.contacts.count; i++) {
        INCallRecord *record = [[INCallRecord alloc] initWithIdentifier:[NSString stringWithFormat:@"%lu", records.count] dateCreated:[NSDate date] caller:[intent.contacts objectAtIndex:i]
            callRecordType:INCallRecordTypeOutgoing callCapability:INCallCapabilityUnknown callDuration:[NSNumber numberWithInt:0] unseen:false];
        [records addObject:record];
    }
    if (records.count == 1) {
        completion([NSClassFromString(@"INCallRecordResolutionResult") performSelector:NSSelectorFromString(@"successWithResolvedCallRecord:") withObject:records.firstObject]);
    }
    else if (records.count > 1) {
        completion([NSClassFromString(@"INCallRecordResolutionResult") performSelector:NSSelectorFromString(@"disambiguationWithCallRecordsToDisambiguate:") withObject:records]);
    }
    else {
        completion([NSClassFromString(@"INCallRecordResolutionResult") performSelector:NSSelectorFromString(@"needsValue")]);
    }
}

-  (void) resolveContactsForStartCall:(INStartCallIntent *)intent withCompletion:(void (^)(NSArray<INStartCallContactResolutionResult *> *resolutionResults))completion
{
    NSMutableArray<INStartCallContactResolutionResult *> *resolutionResults = [NSMutableArray array];
    int i, j;

    if (intent.contacts.count == 0) {
        [resolutionResults addObject:[INStartCallContactResolutionResult needsValue]];
    }
    else {
        NSMutableArray<INPerson *> *recipients = [NSMutableArray array];
        for (i = 0; i < intent.contacts.count; i++) {
            INPerson *contact = [intent.contacts objectAtIndex:i];
            if ([contact respondsToSelector:@selector(siriMatches)] && contact.siriMatches && (contact.siriMatches.count != 0)) {
                for (j = 0; j < contact.siriMatches.count; j++) {
                    [recipients addObject:[contact.siriMatches objectAtIndex:j]];
                }
            }
            else {
                [recipients addObject:contact];
            }
        }
        if (recipients.count == 1) {
            [resolutionResults addObject:[INStartCallContactResolutionResult successWithResolvedPerson:recipients.firstObject]];
        }
        else if (recipients.count > 1) {
            [resolutionResults addObject:[INStartCallContactResolutionResult disambiguationWithPeopleToDisambiguate:recipients]];
        }
        else {
            [resolutionResults addObject:[INStartCallContactResolutionResult unsupported]];
        }
    }
    completion(resolutionResults);
}

- (void) confirmStartCall:(INStartCallIntent *)intent completion:(void (^)(INStartCallIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartCallIntent class])];
    INStartCallIntentResponse *response = [[INStartCallIntentResponse alloc] initWithCode:INStartCallIntentResponseCodeReady userActivity:userActivity];
    completion(response);
}

- (void) handleStartCall:(INStartCallIntent *)intent completion:(void (^)(INStartCallIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartCallIntent class])];
    INStartCallIntentResponse *response = [[INStartCallIntentResponse alloc] initWithCode:INStartCallIntentResponseCodeContinueInApp userActivity:userActivity];
    completion(response);
}

#pragma mark - INStartAudioCallIntentHandling

- (void) resolveContactsForStartAudioCall:(INStartAudioCallIntent *)intent withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion
{
    NSMutableArray<INPersonResolutionResult *> *resolutionResults = [NSMutableArray array];
    int i, j;

    if (intent.contacts.count == 0) {
        [resolutionResults addObject:[INPersonResolutionResult needsValue]];
    }
    else {
        NSMutableArray<INPerson *> *recipients = [NSMutableArray array];
        for (i = 0; i < intent.contacts.count; i++) {
            INPerson *contact = [intent.contacts objectAtIndex:i];
            if ([contact respondsToSelector:@selector(siriMatches)] && contact.siriMatches && (contact.siriMatches.count != 0)) {
                for (j = 0; j < contact.siriMatches.count; j++) {
                    [recipients addObject:[contact.siriMatches objectAtIndex:j]];
                }
            }
            else {
                [recipients addObject:contact];
            }
        }
        if (recipients.count == 1) {
            [resolutionResults addObject:[INPersonResolutionResult successWithResolvedPerson:recipients.firstObject]];
        }
        else if (recipients.count > 1) {
            [resolutionResults addObject:[INPersonResolutionResult disambiguationWithPeopleToDisambiguate:recipients]];
        }
        else {
            [resolutionResults addObject:[INPersonResolutionResult unsupported]];
        }
    }
    completion(resolutionResults);
}

- (void) confirmStartAudioCall:(INStartAudioCallIntent *)intent completion:(void (^)(INStartAudioCallIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartAudioCallIntent class])];
    INStartAudioCallIntentResponse *response = [[INStartAudioCallIntentResponse alloc] initWithCode:INStartAudioCallIntentResponseCodeReady userActivity:userActivity];
    completion(response);
}

- (void) handleStartAudioCall:(INStartAudioCallIntent *)intent completion:(void (^)(INStartAudioCallIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartAudioCallIntent class])];
    INStartAudioCallIntentResponse *response = [[INStartAudioCallIntentResponse alloc] initWithCode:INStartAudioCallIntentResponseCodeContinueInApp userActivity:userActivity];
    completion(response);
}

#pragma mark - INStartVideoCallIntentHandling

- (void) resolveContactsForStartVideoCall:(INStartVideoCallIntent *)intent withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion
{
    NSMutableArray<INPersonResolutionResult *> *resolutionResults = [NSMutableArray array];
    int i, j;

    if (intent.contacts.count == 0) {
        [resolutionResults addObject:[INPersonResolutionResult needsValue]];
    }
    else {
        NSMutableArray<INPerson *> *recipients = [NSMutableArray array];
        for (i = 0; i < intent.contacts.count; i++) {
            INPerson *contact = [intent.contacts objectAtIndex:i];
            if ([contact respondsToSelector:@selector(siriMatches)] && contact.siriMatches && (contact.siriMatches.count != 0)) {
                for (j = 0; j < contact.siriMatches.count; j++) {
                    [recipients addObject:[contact.siriMatches objectAtIndex:j]];
                }
            }
            else {
                [recipients addObject:contact];
            }
        }
        if (recipients.count == 1) {
            [resolutionResults addObject:[INPersonResolutionResult successWithResolvedPerson:recipients.firstObject]];
        }
        else if (recipients.count > 1) {
            [resolutionResults addObject:[INPersonResolutionResult disambiguationWithPeopleToDisambiguate:recipients]];
        }
        else {
            [resolutionResults addObject:[INPersonResolutionResult unsupported]];
        }
    }
    completion(resolutionResults);
}

- (void) confirmStartVideoCall:(INStartVideoCallIntent *)intent completion:(void (^)(INStartVideoCallIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartVideoCallIntent class])];
    INStartVideoCallIntentResponse *response = [[INStartVideoCallIntentResponse alloc] initWithCode:INStartVideoCallIntentResponseCodeReady userActivity:userActivity];
    completion(response);
}

- (void) handleStartVideoCall:(INStartVideoCallIntent *)intent completion:(void (^)(INStartVideoCallIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartVideoCallIntent class])];
    INStartVideoCallIntentResponse *response = [[INStartVideoCallIntentResponse alloc] initWithCode:INStartVideoCallIntentResponseCodeContinueInApp userActivity:userActivity];
    completion(response);
}

#pragma mark - INSearchCallHistoryIntentHandling

- (void) resolveCallTypesForSearchCallHistory:(INSearchCallHistoryIntent *)intent withCompletion:(void (^)(INCallRecordTypeOptionsResolutionResult *resolutionResult))completion
{
    completion([INCallRecordTypeOptionsResolutionResult successWithResolvedCallRecordTypeOptions:intent.callTypes]);
}

- (void) resolveCallTypeForSearchCallHistory:(INSearchCallHistoryIntent *)intent withCompletion:(void (^)(INCallRecordTypeResolutionResult *resolutionResult))completion
{
    completion([INCallRecordTypeResolutionResult successWithResolvedCallRecordType:intent.callType]);
}

- (void) resolveRecipientForSearchCallHistory:(INSearchCallHistoryIntent *)intent withCompletion:(void (^)(INPersonResolutionResult *resolutionResult))completion
{
    completion([INPersonResolutionResult successWithResolvedPerson:intent.recipient]);
}

- (void) resolveDateCreatedForSearchCallHistory:(INSearchCallHistoryIntent *)intent withCompletion:(void (^)(INDateComponentsRangeResolutionResult *resolutionResult))completion
{
    completion([INDateComponentsRangeResolutionResult successWithResolvedDateComponentsRange:intent.dateCreated]);
}

- (void) resolveUnseenForSearchCallHistory:(INSearchCallHistoryIntent *)intent withCompletion:(void (^)(INBooleanResolutionResult *resolutionResult))completion
{
    completion([INBooleanResolutionResult successWithResolvedValue:true]);
}

- (void) confirmSearchCallHistory:(INSearchCallHistoryIntent *)intent completion:(void (^)(INSearchCallHistoryIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSearchCallHistoryIntent class])];
    INSearchCallHistoryIntentResponse *response = [[INSearchCallHistoryIntentResponse alloc] initWithCode:INSearchCallHistoryIntentResponseCodeReady userActivity:userActivity];
    completion(response);
}

- (void) handleSearchCallHistory:(INSearchCallHistoryIntent *)intent completion:(void (^)(INSearchCallHistoryIntentResponse *response))completion
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSearchCallHistoryIntent class])];
    INSearchCallHistoryIntentResponse *response = [[INSearchCallHistoryIntentResponse alloc] initWithCode:INSearchCallHistoryIntentResponseCodeFailureRequiringAppLaunch userActivity:userActivity];
    completion(response);
}

#pragma mark - INSendMessageIntentHandling

// You can test your example integration by saying things to Siri like:
// "Send a message using <myApp>"
// "<myApp> John saying hello"
// "Search for messages in <myApp>"

// Implement resolution methods to provide additional information about your intent (optional).
- (void) resolveRecipientsForSendMessage:(INSendMessageIntent *)intent with:(void (^)(NSArray<INSendMessageRecipientResolutionResult *> *resolutionResults))completion
{
    NSMutableArray<INSendMessageRecipientResolutionResult *> *resolutionResults = [NSMutableArray array];
    int i, j;

    if (intent.recipients.count == 0) {
        // If no recipients were provided we'll need to prompt for a value.
        [resolutionResults addObject:[INSendMessageRecipientResolutionResult needsValue]];
    }
    else {
        NSMutableArray<INPerson *> *recipients = [NSMutableArray array];
        for (i = 0; i < intent.recipients.count; i++) {
            INPerson *contact = [intent.recipients objectAtIndex:i];
            if ([contact respondsToSelector:@selector(siriMatches)] && contact.siriMatches && (contact.siriMatches.count != 0)) {
                for (j = 0; j < contact.siriMatches.count; j++) {
                    [recipients addObject:[contact.siriMatches objectAtIndex:j]];
                }
            }
            else {
                [recipients addObject:contact];
            }
        }
        if (recipients.count == 1) {
            // We have exactly one matching contact
            [resolutionResults addObject:[INSendMessageRecipientResolutionResult successWithResolvedPerson:recipients.firstObject]];
        }
        else if (recipients.count > 1) {
            // We need Siri's help to ask user to pick one from the matches.
            [resolutionResults addObject:[INSendMessageRecipientResolutionResult disambiguationWithPeopleToDisambiguate:recipients]];
        }
        else {
            // We have no contacts matching the description provided
            [resolutionResults addObject:[INSendMessageRecipientResolutionResult unsupported]];
        }
    }
    completion(resolutionResults);
}

- (void) resolveContentForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(INStringResolutionResult *resolutionResult))completion
{
    NSString *text = intent.content;
    if (text && ![text isEqualToString:@""]) {
        completion([INStringResolutionResult successWithResolvedString:text]);
    } else {
        completion([INStringResolutionResult needsValue]);
    }
}

// Once resolution is completed, perform validation on the intent and provide confirmation (optional).

- (void) confirmSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse *response))completion
{
    // Verify user is authenticated and your app is ready to send a message.
    
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
    INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeReady userActivity:userActivity];
    completion(response);
}

// Handle the completed intent (required).

- (void) handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse *response))completion
{
    // Implement your application logic to send a message here.
    
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
    INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
    completion(response);
}

// Implement handlers for each intent you wish to handle.  As an example for messages, you may wish to also handle searchForMessages and setMessageAttributes.

#pragma mark - INSearchForMessagesIntentHandling

- (void) handleSearchForMessages:(INSearchForMessagesIntent *)intent completion:(void (^)(INSearchForMessagesIntentResponse *response))completion
{
    // Implement your application logic to find a message that matches the information in the intent.
    
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSearchForMessagesIntent class])];
    INSearchForMessagesIntentResponse *response = [[INSearchForMessagesIntentResponse alloc] initWithCode:INSearchForMessagesIntentResponseCodeSuccess userActivity:userActivity];
    // Initialize with found message's attributes
    response.messages = @[[[INMessage alloc]
        initWithIdentifier:@"identifier"
        content:@"I am so excited about SiriKit!"
        dateSent:[NSDate date]
        sender:[[INPerson alloc] initWithPersonHandle:[[INPersonHandle alloc] initWithValue:@"sarah@example.com" type:INPersonHandleTypeEmailAddress] nameComponents:nil displayName:@"Sarah" image:nil contactIdentifier:nil customIdentifier:nil]
        recipients:@[[[INPerson alloc] initWithPersonHandle:[[INPersonHandle alloc] initWithValue:@"+1-415-555-5555" type:INPersonHandleTypePhoneNumber] nameComponents:nil displayName:@"John" image:nil contactIdentifier:nil customIdentifier:nil]]
    ]];
    completion(response);
}

#pragma mark - INSetMessageAttributeIntentHandling

- (void) handleSetMessageAttribute:(INSetMessageAttributeIntent *)intent completion:(void (^)(INSetMessageAttributeIntentResponse *response))completion
{
    // Implement your application logic to set the message attribute here.
    
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSetMessageAttributeIntent class])];
    INSetMessageAttributeIntentResponse *response = [[INSetMessageAttributeIntentResponse alloc] initWithCode:INSetMessageAttributeIntentResponseCodeSuccess userActivity:userActivity];
    completion(response);
}

@end
