//
//  MVMCoreLoadRequestOperation.h
//  myverizon
//
//  Created by Scott Pfeil on 11/11/15.
//  Copyright © 2015 Verizon Wireless. All rights reserved.
//
//  The meat and potatos. Handles the load protocol. Should NOT be called on the main queue.

#import <MVMCore/MVMCoreOperation.h>
#import <MVMCore/MVMCoreLoadDelegateProtocol.h>
#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
#import <MVMCore/MVMCoreActionDelegateProtocol.h>

@class MVMCoreRequestParameters;
@class MVMCoreLoadObject;
@class DelegateObject;

@interface MVMCoreLoadRequestOperation : MVMCoreOperation <MVMCorePresentationDelegateProtocol>

@property (nullable, strong, nonatomic) MVMCoreRequestParameters *requestParameters;
@property (nullable, strong, nonatomic) MVMCoreLoadObject *loadObject;
@property (nullable, strong, nonatomic) NSDictionary *dataForPage;
@property (nullable, strong, nonatomic) NSObject <MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol> *delegate;// __deprecated;
@property (nullable, strong, nonatomic) DelegateObject *delegateObject;
@property (nonatomic) BOOL backgroundLoad;
@property (nonatomic, getter=areDependenciesAdded) BOOL dependenciesAdded;

// Initializes the operation with the request parameters object, data for page, and mvm view controller to handle the loading with.
- (nullable instancetype)initWithRequestParameters:(nullable MVMCoreRequestParameters *)requestParameters dataForPage:(nullable NSDictionary *)dataForPage delegateObject:(nullable DelegateObject *)delegateObject backgroundLoad:(BOOL)backgroundLoad;

// Initializes the operation with the load object, data for page, and mvm view controller to handle the loading with. Can be used for loading a screen without going to the cache or server.
- (nullable instancetype)initWithLoadObject:(nullable MVMCoreLoadObject *)loadObject backgroundLoad:(BOOL)backgroundLoad;

/* Checks the cache for the data and calls the completion handler with any found data.
 * @param completionHandler The block that gets called with any fetched data. */
+ (void)checkCacheForDataForRequest:(nonnull MVMCoreRequestParameters *)requestParameters completionHandler:(nonnull void (^)(NSDictionary * _Nullable pageFromCache, NSDictionary * _Nullable modulesFromCache))completionHandler;

/** Sends the request to the server with the given parameters.
 *  @param loadObject The load object for this operation. Should contain any data loaded from the cache.
 *  @param completionHandler gets called with the json assuming there were no errors. Any errors will be handled and completion handler will not be called. */
+ (void)sendRequest:(nonnull MVMCoreRequestParameters *)requestParameters loadObject:(nonnull MVMCoreLoadObject *)loadObject completionHandler:(nonnull void (^)(NSDictionary * _Nullable json))completionHandler;

/* A helper function. If we shouldn't continue, finish or abort with error. If we should continue, call the continue block. Error is not handled if we continue.
 * @param errorBlock The block that gets called when we shouldn't continue for any reason.
 * @param completionHandler The block that gets when we should continue. */
+ (void)handleShouldContinue:(BOOL)shouldContinue error:(nullable MVMCoreErrorObject *)error loadObject:(nullable MVMCoreLoadObject *)loadObject errorBlock:(nullable void (^)(void))errorBlock continueBlock:(nonnull void (^)(void))continueBlock;

// Processes the json retrieved from the server. Will cache the json and process it.
+ (void)processJSONFromServer:(nonnull NSDictionary *)jsonDictionary loadObject:(nonnull MVMCoreLoadObject *)loadObject completionHandler:(nonnull void (^)(MVMCoreLoadObject * _Nonnull loadObject, MVMCoreErrorObject * _Nullable error))completionHandler;

/** Handles the load object now that the json is retrieved. Loads a page when asked and finishes up the load.
 *  @param loadObject               The load data from the cache or server.
 *  @param error                    A possible error that was caught and needs to be passed to load finished. It has already been handled.*/
+ (void)handleLoadObject:(nonnull MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error;

/** Checks the json for any errors. First, checks the response info for standard errors. Then, allows the core delegate to handle global errors. Then, allows the delegate to handle controller specific errors.
 *  @param loadObject               The load data from the cache or server.
 *  @param completionHandler        The completion handler to load once finished. Returns if we should continue loading or not. */
+ (void)checkForErrorsInJSONForLoadObject:(nonnull MVMCoreLoadObject *)loadObject completionHandler:(nonnull void (^)(BOOL shouldContinueLoad, MVMCoreLoadObject * _Nullable loadObject, MVMCoreErrorObject * _Nullable error))completionHandler;

/** Caches the modules.
 *  @param modules                  a dictionary of modules.
 *  @param loadObject               The load data from the cache or server.
 *  @param error                    The error object passed in will be set in the case of an error.
 *  @return True if the calling process should continue. */
+ (BOOL)cacheModules:(nullable NSDictionary *)modules loadObject:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error;

/** Caches the additional pages.
 *  @param pages                    a dictionary of pages.
 *  @param loadObject               The load data from the cache or server.
 *  @param error                    The error object passed in will be set in the case of an error.
 *  @return True if the calling process should continue. */
+ (BOOL)cachePages:(nullable NSDictionary *)pages loadObject:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error;

/** Creates the view controller based on the load object passed in.
 *  @param loadObject               The load data from the cache or server.
 *  @param completionHandler        The completion handler to load once finished. Returns any loaded view controller and the load.*/
+ (void)createViewControllerWithLoadObject:(nonnull MVMCoreLoadObject *)loadObject completionHandler:(nonnull void (^)(UIViewController <MVMCoreViewControllerProtocol> * _Nullable viewController, MVMCoreLoadObject *_Nonnull loadObject))completionHandler;

// Displays the view controller to the screen.
+ (void)displayViewController:(nonnull UIViewController <MVMCoreViewControllerProtocol> *)viewController loadObject:(nullable MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error;

// Handles the error based on the error object passed in. May log and/or display the error.
+ (void)handleError:(nonnull MVMCoreErrorObject *)error loadObject:(nonnull MVMCoreLoadObject *)loadObject showAlertForErrorIfApplicable:(BOOL)showAlertForErrorIfApplicable;

// Shows the appropriate alert tyle for the given response info and/or error.
+ (void)createAndShowAlertForLoadObject:(nullable MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error delegateObject:(nullable DelegateObject *)delegateObject;

/** Called when the load was finished due to an error. Handles the error and ends the load.
 *  @param error                    The error that occured. May be logged depending.
 *  @param loadObject               The load data for the error. **/
+ (void)loadAbortedWithError:(nonnull MVMCoreErrorObject *)error loadObject:(nonnull MVMCoreLoadObject *)loadObject;

/** Called when the load is finished. Ends the load. Lets the delegate know that the load finished and passes along any error that may have caused an abort.
 *  @param errorObject              An error if one caused an abort.
 *  @param loadedViewController     If a view controller was loaded or not, it will be passed here.
 *  @param loadObject               The load data **/
+ (void)loadFinished:(nonnull MVMCoreLoadObject *)loadObject loadedViewController:(nullable UIViewController <MVMCoreViewControllerProtocol> *)loadedViewController errorObject:(nullable MVMCoreErrorObject *)errorObject;

#pragma mark - Deprecated

- (nullable instancetype)initWithRequestParameters:(nullable MVMCoreRequestParameters *)requestParameters dataForPage:(nullable NSDictionary *)dataForPage delegate:(nullable NSObject<MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)delegate backgroundLoad:(BOOL)backgroundLoad __deprecated;

@end
