//
//  MVMCoreAlertObject.m
//  myverizon
//
//  Created by Scott Pfeil on 11/21/14.
//  Copyright (c) 2014 Verizon Wireless. All rights reserved.
//

#import "MVMCoreAlertObject.h"
#import "MVMCoreAlertHandler.h"
#import "MVMCoreTopAlertObject.h"
#import <MVMCore/MVMCoreCache.h>
#import <MVMCore/MVMCoreErrorConstants.h>
#import <MVMCore/MVMCoreErrorObject.h>
#import <MVMCore/MVMCoreLoadObject.h>
#import <MVMCore/MVMCoreGetterUtility.h>
#import <MVMCore/NSDictionary+MFConvenience.h>
#import <MVMCore/MVMCoreHardcodedStringsConstants.h>
#import <MVMCore/MVMCoreJSONConstants.h>
#import <MVMCore/MVMCoreActionHandler.h>
#import <MVMCore/MVMCore-Swift.h>
#import <MVMCoreUI/MVMCoreUI-Swift.h>

@interface MVMCoreAlertObject ()

@property (strong, nonatomic) MVMCoreLoadObject *loadObject;
@property (nullable, strong, nonatomic) NSString *systemDomain;
@property (nullable, strong, nonatomic) MVMCoreTopAlertObject *topAlertObject;
@end

@implementation MVMCoreAlertObject

+ (nullable instancetype)alertObjectForLoadObject:(nullable MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error delegateObject:(nullable DelegateObject *)delegateObject {
    
    MVMCoreAlertObject *alert = nil;
    if (!error || [ErrorDomainServer isEqualToString:error.domain]) {
        alert = [MVMCoreAlertObject alertObjectForPageType:loadObject.pageType responseInfo:loadObject.responseInfoMap additionalData:loadObject.dataForPage delegateObject:delegateObject];
    } else {
        alert = [[MVMCoreAlertObject alloc] initPopupAlertWithError:error isGreedy:NO];
    }
    
    // only if actions are empty, then go inside and set OK as default action
    if (alert.type == MFAlertTypePopup && alert.actions.count == 0) {
        alert.defaultAction = YES;
        alert.actions = @[[UIAlertAction actionWithTitle:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedOK] style:UIAlertActionStyleDefault handler:nil]];
    }
    return alert;
}

+ (nullable instancetype)alertObjectForPageType:(nullable NSString *)pageType responseInfo:(nullable NSDictionary *)responseInfo additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject {
    MVMCoreUIDelegateObject *alertDelegateObject = nil;
    if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
        alertDelegateObject = (MVMCoreUIDelegateObject *)delegateObject;
    }
    
    __block MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
    alert.title = [responseInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
    alert.message = [responseInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
    
    NSString *messageStyle = [responseInfo stringForKey:KeyMessageStyle];
    if ([ValueTypeFieldErrors isEqualToString:[responseInfo string:KeyType]]) {
        
        // field errors.
        alert.type = MFAlertTypeField;
        alert.fieldErrors = [responseInfo array:ValueTypeFieldErrors];
    } else {

        // Check for top alert (persistent or regular).
        if ([messageStyle isEqualToString:ValueMessageStyleTopPersistent] || [messageStyle isEqualToString:ValueMessageStyleTop]) {
        
            alert.topAlertObject = [[MVMCoreTopAlertObject alloc] initWithResponseInfo:responseInfo];
            alert.topAlertObject.delegate = alertDelegateObject.topAlertDelegate;
            alert.topAlertObject.pageType = pageType;
            alert.type = MFAlertTypeTop;
        } else if ([messageStyle isEqualToString:ValueMessageStylePopup]) {
            
            // Perform a popup.
            alert.type = MFAlertTypePopup;
            alert.alertStyle = UIAlertControllerStyleAlert;
            
            // Check if we have a popup driven by page object (otherwise by default it will just use response info title message with an OK button).
            NSString *pageTypeForPopup = [responseInfo stringForKey:@"popupPageType"];
            [[MVMCoreCache sharedCache] fetchJSONForPageType:pageTypeForPopup queue:nil waitUntilFinished:YES completionHandler:^(NSDictionary * _Nullable jsonDictionary) {
                
                MVMCoreErrorObject *error = nil;
                MVMCoreAlertObject *popupAlert = [MVMCoreAlertObject alertObjectWithPage:jsonDictionary isGreedy:NO additionalData:additionalData delegateObject:delegateObject error:&error];
                if (error) {
                    
                    // Error, popup page not found for page type.
                    popupAlert = [[MVMCoreAlertObject alloc] initPopupAlertWithError:error isGreedy:NO];
                }
                
                if (popupAlert) {
                    alert = popupAlert;
                }
            }];
        } else if (messageStyle.length == 0 && pageType) {
            
            // No message style!
            alert.type = MFAlertTypeNone;
        } else {
            
            // Default to popup
            alert.type = MFAlertTypePopup;
            alert.alertStyle = UIAlertControllerStyleAlert;
        }
    }
    alert.alertDelegate = alertDelegateObject.alertDelegate;
    return alert;
}

- (nullable instancetype)initPopupAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nonnull NSArray *)actions isGreedy:(BOOL)isGreedy {
    if (self = [super init]) {
        self.title = title;
        self.message = message;
        self.actions = actions;
        self.isGreedy = isGreedy;
        self.type = MFAlertTypePopup;
        self.alertStyle = UIAlertControllerStyleAlert;
    }
    return self;
}

- (nullable instancetype)initPopupAlertWithError:(nullable MVMCoreErrorObject *)error isGreedy:(BOOL)isGreedy {
    
    if (self = [super init]) {
        self.title = error.title;
        self.message = [NSString stringWithFormat:@"%@ (%@)",error.messageToDisplay,[error stringErrorCode]];
        self.actions = @[[UIAlertAction actionWithTitle:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedOK] style:UIAlertActionStyleDefault handler:nil]];
        self.defaultAction = YES;
        self.isGreedy = isGreedy;
        self.type = MFAlertTypePopup;
        self.alertStyle = UIAlertControllerStyleAlert;
    }
    return self;
}

- (nullable instancetype)initPopupAlertWithError:(nullable MVMCoreErrorObject *)error actions:(nonnull NSArray *)actions isGreedy:(BOOL)isGreedy {
    
    if (self = [super init]) {
        self.title = error.title;
        self.message = [NSString stringWithFormat:@"%@ (%@)",error.messageToDisplay,[error stringErrorCode]];
        self.actions = actions;
        self.isGreedy = isGreedy;
        self.type = MFAlertTypePopup;
        self.alertStyle = UIAlertControllerStyleAlert;
    }
    return self;
}

+ (nullable instancetype)alertObjectWithPage:(nullable NSDictionary *)page isGreedy:(BOOL)isGreedy additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error {
    
    MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
    alert.title = [page string:KeyTitle] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
    alert.pageJson = page;
    alert.message = [page string:KeyMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
    alert.isGreedy = isGreedy;
    alert.type = MFAlertTypePopup;
    alert.alertStyle = UIAlertControllerStyleAlert;

    NSArray <NSDictionary *> *actions = [page array:KeyLinks];
    NSMutableArray <UIAlertAction *> *actionsForAlert = [NSMutableArray array];
    for (NSDictionary *actionMap in actions) {
        [actionsForAlert addObject:[UIAlertAction actionWithTitle:[actionMap stringForKey:KeyTitle] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegateObject:delegateObject];
        }]];
    }
    alert.actions = actionsForAlert;

    if ((alert.title.length > 0 || alert.message.length > 0) && alert.actions.count > 0) {
        return alert;
    } else {
        if (error) {
            id delegate = [delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]] ? ((MVMCoreUIDelegateObject *)delegateObject).alertDelegate : nil;
            *error = [[MVMCoreErrorObject alloc] initWithTitle:nil message:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess] code:ErrorCodePopupFailed domain:ErrorDomainNative location:[NSString stringWithFormat:@"%@_Popup_pageType:%@",NSStringFromClass([delegate class]),[page stringForKey:KeyPageType]]];
        }
        return nil;
    }
}

- (void)showAlert {
    
    switch (self.type) {
        case MFAlertTypeField:
            self.textFieldErrorHandler(self.fieldErrors);
            break;
        case MFAlertTypeTop:
            [[MVMCoreAlertHandler sharedAlertHandler] showTopAlertWithObject:self.topAlertObject];
            break;
        case MFAlertTypePopup:
            [[MVMCoreAlertHandler sharedAlertHandler] showAlertWithAlertObject:self];
            break;
        default:
            break;
    }
}

#pragma mark - Deprecated

+ (nullable instancetype)alertObjectForLoadObject:(nullable MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error actionDelegate:(nullable NSObject <MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)actionDelegate {
    
    MVMCoreAlertObject *alert = nil;
    if (!error || [ErrorDomainServer isEqualToString:error.domain]) {
        alert = [MVMCoreAlertObject alertObjectForPageType:loadObject.pageType responseInfo:loadObject.responseInfoMap additionalData:loadObject.dataForPage actionDelegate:actionDelegate];
    } else {
        alert = [[MVMCoreAlertObject alloc] initPopupAlertWithError:error isGreedy:NO];
    }
    
    // only if actions are empty, then go inside and set OK as default action
    if (alert.type == MFAlertTypePopup && alert.actions.count == 0) {
        alert.defaultAction = YES;
        alert.actions = @[[UIAlertAction actionWithTitle:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedOK] style:UIAlertActionStyleDefault handler:nil]];
    }
    return alert;
}

+ (nullable instancetype)alertObjectForPageType:(nullable NSString *)pageType responseInfo:(nullable NSDictionary *)responseInfo additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)actionDelegate {
    
    __block MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
    alert.title = [responseInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
    alert.message = [responseInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
    NSString *messageStyle = [responseInfo stringForKey:KeyMessageStyle];
    if ([ValueTypeFieldErrors isEqualToString:[responseInfo string:KeyType]]) {
        
        // field errors.
        alert.type = MFAlertTypeField;
        alert.fieldErrors = [responseInfo array:ValueTypeFieldErrors];
    } else {
        
        // Check for top alert (persistent or regular).
        if ([messageStyle isEqualToString:ValueMessageStyleTopPersistent] || [messageStyle isEqualToString:ValueMessageStyleTop]) {
            
            alert.topAlertObject = [[MVMCoreTopAlertObject alloc] initWithResponseInfo:responseInfo];
            if ([actionDelegate conformsToProtocol:@protocol(MVMCoreTopAlertDelegateProtocol)]) {
                alert.topAlertObject.delegate = (NSObject <MVMCoreTopAlertDelegateProtocol> *)actionDelegate;
            }
            alert.topAlertObject.pageType = pageType;
            alert.type = MFAlertTypeTop;
        } else if ([messageStyle isEqualToString:ValueMessageStylePopup]) {
            
            // Perform a popup.
            alert.type = MFAlertTypePopup;
            alert.alertStyle = UIAlertControllerStyleAlert;
            
            // Check if we have a popup driven by page object (otherwise by default it will just use response info title message with an OK button).
            NSString *pageTypeForPopup = [responseInfo stringForKey:@"popupPageType"];
            [[MVMCoreCache sharedCache] fetchJSONForPageType:pageTypeForPopup queue:nil waitUntilFinished:YES completionHandler:^(NSDictionary * _Nullable jsonDictionary) {
                
                MVMCoreErrorObject *error = nil;
                MVMCoreAlertObject *popupAlert = [MVMCoreAlertObject alertObjectWithPage:jsonDictionary isGreedy:NO additionalData:additionalData delegate:actionDelegate error:&error];
                if (error) {
                    
                    // Error, popup page not found for page type.
                    popupAlert = [[MVMCoreAlertObject alloc] initPopupAlertWithError:error isGreedy:NO];
                }
                
                if (popupAlert) {
                    alert = popupAlert;
                }
            }];
        } else if (messageStyle.length == 0 && pageType) {
            
            // No message style!
            alert.type = MFAlertTypeNone;
        } else {
            
            // Default to popup
            alert.type = MFAlertTypePopup;
            alert.alertStyle = UIAlertControllerStyleAlert;
        }
    }
    if ([actionDelegate conformsToProtocol:@protocol(MVMCoreAlertDelegateProtocol)]) {
        alert.alertDelegate = (NSObject <MVMCoreAlertDelegateProtocol> *)actionDelegate;
    }
    return alert;
}

+ (nullable instancetype)alertObjectWithPage:(nullable NSDictionary *)page isGreedy:(BOOL)isGreedy additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject <MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)delegate error:(MVMCoreErrorObject *_Nullable *_Nullable)error {
    
    MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
    alert.title = [page string:KeyTitle] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
    alert.pageJson = page;
    alert.message = [page string:KeyMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
    alert.isGreedy = isGreedy;
    alert.type = MFAlertTypePopup;
    alert.alertStyle = UIAlertControllerStyleAlert;
    
    NSArray <NSDictionary *> *actions = [page array:KeyLinks];
    NSMutableArray <UIAlertAction *> *actionsForAlert = [NSMutableArray array];
    for (NSDictionary *actionMap in actions) {
        [actionsForAlert addObject:[UIAlertAction actionWithTitle:[actionMap stringForKey:KeyTitle] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:delegate];
        }]];
    }
    alert.actions = actionsForAlert;
    
    if ((alert.title.length > 0 || alert.message.length > 0) && alert.actions.count > 0) {
        return alert;
    } else {
        if (error) {
            *error = [[MVMCoreErrorObject alloc] initWithTitle:nil messageToLog:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess] code:ErrorCodePopupFailed domain:ErrorDomainNative location:[NSString stringWithFormat:@"%@_Popup_pageType:%@",NSStringFromClass([delegate class]),[page stringForKey:KeyPageType]]];
        }
        return nil;
    }
}

@end
