//
//  MFViewController.h
//  myverizon
//
//  Created by Scott Pfeil on 11/26/13.
//  Copyright (c) 2013 Verizon Wireless. All rights reserved.
//
//  The base view controller. Any view controller that is part of the app flow should be subclassed from this object.

#import <UIKit/UIKit.h>
@import MVMCore.MVMCoreErrorObject;
@import MVMCore.MVMCoreLoadDelegateProtocol;
@import MVMCore.MVMCorePresentationDelegateProtocol;
@import MVMCore.MVMCoreActionDelegateProtocol;
@import MVMCore.NSDictionary_MFConvenience;
@import MVMCore.MVMCoreLoadObject;
@import MVMCore.MVMCoreJSONConstants;
@import MVMCore.MVMCoreRequestParameters;
@import MVMCore.MVMCoreActionHandler;
@import MVMCore.MVMCoreTopAlertObject;
@import MVMCore.MVMCoreAlertObject;
@import MVMCore.MVMCoreViewControllerProtocol;
@import MVMCore.MVMCoreViewManagerViewControllerProtocol;
@import MVMCore.MVMCoreViewManagerProtocol;

#import <MVMCoreUI/MFTextField.h>
#import <MVMCoreUI/ButtonDelegateProtocol.h>
#import <MVMCoreUI/MFStyler.h>
#import <MVMCoreUI/MVMCoreUIDetailViewProtocol.h>
#import <MVMCoreUI/MoleculeDelegateProtocol.h>

@class MainMenuViewController;
@class MVMCoreUITabBarPageControlViewController;
@class MVMAnimationManager;
@class DelegateObject;

@interface MFViewController : UIViewController <MVMCoreLoadDelegateProtocol, MVMCorePresentationDelegateProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, MFTextFieldDelegate, ButtonDelegateProtocol, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MVMCoreUIDetailViewProtocol, MoleculeDelegateProtocol>

// Stores the load object that this screen was loaded with.
@property (nullable, strong, nonatomic) MVMCoreLoadObject *loadObject;

// The current selected text field.
@property (nullable, weak, nonatomic) __block id selectedField;

// Flags for if the master and support should be accessible. These are set initially and then checked everytime view will appear to make sure that the support and master buttons are showing if they should be.
// ** When set, they will update the support and master buttons
@property (nonatomic) BOOL masterShouldBeAccessible;
@property (nonatomic) BOOL supportShouldBeAccessible;

// A flag for if we need to update the UI or not next time viewDidLayoutSubviews is called.
@property (nonatomic) BOOL needToUpdateUI;

// flag used to tell if we need to updateViews based on rotation.
@property (nonatomic) BOOL needToupdateUIOnScreenSizeChanges;


// A flag for if this viewControler should trigger MFAnimationController's StartAnimations in viewDidAppear
@property (nonatomic) BOOL shouldTriggerStartAnimations;

// The page type for this screen.
@property (nullable, strong, nonatomic) NSString *pageType;

// Set if this page is containted in a manager.
@property (nullable, weak, nonatomic) UIViewController <MVMCoreViewManagerProtocol>*manager;

// Convenience for mf. Set if this page is containted in a tab bar page control.
@property (nullable, weak, nonatomic) MVMCoreUITabBarPageControlViewController *tabBarPageControl;

/* The bottom progress view that is shown in the shop flow */
@property (nullable, nonatomic, strong) UIProgressView *progressView;

// The size of the previous screen configuration. Updates each rotate.
@property (nonatomic) CGSize previousScreenSize;

// The current top alert showing page type
@property (nullable, nonatomic, strong) NSString *currentTopAlertPageType;

#pragma mark - Helpers

// Dismisses this screen.
- (void)dismiss;

// Checks if this view controller is the visible one (not necessarily visible to user, but for the app).
- (BOOL)isVisibleViewController;

// Registers the text field for the error key so that if there is a text field error with this key, the textfield will show the error.
- (void)registerTextField:(nonnull MFTextField *)textField forErrorKey:(nonnull NSString *)errorKey;

// Returns if the screen size has changed.
- (BOOL)screenSizeChanged;

/// If we have new data, this is called. It calls newDataBuildScreen and sets the ui to update.
- (void)newDataBuildAndUpdate;

#pragma mark - Functions To Subclass

// This view controller should subclass this function and check the load to make sure it has all the needed data. Fills the error object if there are any errors. Returns if we should finish the load or not.
- (BOOL)shouldFinishProcessingLoad:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error;

// Sets the screen to use the screen heading.
// it is required in device flow, where we are showing greeting name as screen heading,
//  device details screen heading needs to be updated/refreshed again, if user has changed device nick name
- (nullable NSString *)screenHeading;

// properly set the screen heading message
- (void)setScreenHeadingMessage:(nullable NSString *)screenHeadingMessage;

// There is new data and we need to reset the data for the screen. Refresh all logic based on json dictionary. Can put most view creation logic in here.
- (void)newDataBuildScreen;

// A function that gets called on only the initial load. Meant for subclassing.
- (void)initialLoad __attribute__((objc_requires_super));

// Subclass this function to layout any subviews here. Update constraints based on the screen in here.
- (void)updateViews;

// Called when the back button is pressed. Overwrite for special functionality. Default is to just popviewcontroller.
- (void)backButtonPressed;

// Handles the error. Logs and shows to screen.
- (void)handleErrorAsPopup:(nonnull MVMCoreErrorObject *)error;

#pragma mark - Response Handling

// Called to begin observing for json updates. Called by default in view did load if pageTypesToListenFor returns an array with page types.
- (void)observeForResponseJSONUpdates;

// Stops observing for json objects.
- (void)stopObservingForResponseJSONUpdates;

// Returns an array of page types to observe for when we receive a response with JSON. Subclass this to have the ui update when the returned page types are cached.
- (nullable NSArray *)pageTypesToListenFor;

// Returns an array of modules to observe for when we receive a response with JSON. Subclass this to have the ui update when the returned page types are cached.
- (nullable NSArray *)modulesToListenFor;

/// The function that gets called by the notification center when the JSON is updated, if we have anything we are listening for (pageTypesToListenFor, modulesToListenFor). This function also tells the screen to update (newDataBuildAndUpdate) if we received new json that we were listening for.
- (void)responseJSONUpdated:(nonnull NSNotification *)notification;

/// Sets the page on the load object. Default returns true. Return true if the page is loaded and newDataBuildAndUpdate needs to happen. Can subclass to avoid this.
- (BOOL)newPageLoaded:(nonnull NSDictionary *)page;

/// Appends to the modules on the load object. Default returns true. Return true if the modules are loaded and newDataBuildAndUpdate needs to happen. Can subclass to avoid this.
- (BOOL)newModulesLoaded:(nonnull NSDictionary *)modules;

/** Verifies that all needed modules are loaded
 *  @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)verifyRequiredModulesLoadedForLoadObject:(nullable MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error;

#pragma mark - Navigation Item, Menu, Support, Top Alert

// overide to set the navigation bar tint color
- (nullable UIColor *)navigationBarTintColor;

// Sets the navigation bar color when the screen is loaded. Can be subclassed to change this logic.
- (nonnull UIColor *)navigationBarColor;

// Default is no.
- (BOOL)navigationBarHidden;

// Default is no.
- (BOOL)navigationBarTransparent;

// Handles the navigation bar ui.
- (void)updateNavigationBarUI:(nonnull UINavigationController *)navigationController;

// Returns if the master panel is initially accessible or not. This is always true in the base class. Subclass to override.
- (BOOL)isMasterInitiallyAccessible;

// Returns if the support panel is initially accessible or not. This is always true in the base class. Subclass to override.
- (BOOL)isSupportInitiallyAccessible;

// This returns a server driven flag. By default we don't show support before launchapp unless server says otherwise.
- (BOOL)showRightPanelForScreenBeforeLaunchApp;

// Called when the user presses a menu option. Determines if we should load the option the default way or not.
- (BOOL)mainTableView:(nonnull MainMenuViewController *)mainTableView shouldSelectOptionAtIndexPath:(nonnull NSIndexPath *)indexPath;

#pragma mark - UITextField Functions

// Resigns the first responder.
- (IBAction)textFieldDoneEditing:(nullable id)sender;

// Dismisses the keyboard.
- (void)dismissFieldInput:(nullable id)sender;

#pragma mark - TableView

// For subclassing, returns the number of sections for table. Use this function instead of numberOfSectionsForTableview.
- (NSInteger)getNumberOfSections;

#pragma mark - ButtonDelegateProtocol

// Returns YES by default.
- (BOOL)button:(nonnull NSObject <MFButtonProtocol> *)button shouldPerformActionWithMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;

#pragma mark - MVMCoreActionDelegateProtocol

// track the action which is fired
- (void)logActionWithActionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;

// Asks the load handler to load. standard.
- (void)handleOpenPageForRequestParameters:(nonnull MVMCoreRequestParameters *)requestParameters actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData NS_REQUIRES_SUPER;

// Calls dismiss
- (void)handleBackAction:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;

// This will try to load the previous submission by default and append any additional data.
- (void)prepareRequestForPreviousSubmission:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData submit:(nonnull void (^)(MVMCoreRequestParameters * _Nonnull requestParameters, NSDictionary * _Nullable dataForPage))submit;

// Does nothing at the moment.
- (void)willShowPopupWithAlertObject:(nonnull MVMCoreAlertObject *)alertObject alertJson:(nonnull NSDictionary *)alertJson;

// Handle cancel
- (void)handleCancel:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;

// Calls the default. See MVMCoreActionHandler
- (void)handleUnknownActionType:(nullable NSString *)actionType actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;

// Calls the default. See MVMCoreActionHandler
- (void)handleActionError:(nonnull MVMCoreErrorObject *)error additionalData:(nullable NSDictionary *)additionalData;

// Does nothing
- (void)prepareForOpenOtherAppModule:(nullable NSString *)module;

#pragma mark - MVMCoreLoadDelegateProtocol

/////-----------------------------------------------------------------------------------
// Standard Protocol Functions (refer to the MVMCoreLoadDelegateProtocol for more.
// Listed here in the .h so subclass could call [super] if need be.

// By default, returns YES.
- (BOOL)shouldContinueToErrorPage:(nonnull MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error;

// Calls the default, see LoadHandler.
- (BOOL)handleModuleError:(nonnull NSString *)module loadObject:(nonnull MVMCoreLoadObject *)loadObject error:(nonnull MVMCoreErrorObject *)error;

// By default, lets the alert object handle showing itself.
- (nullable MVMCoreAlertObject *)alertObjectToShow:(nonnull MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)errorObject;

// By default, goes through all of the fields register with registerTextField and sets the error for them if needed.
- (void)handleFieldErrors:(nullable NSArray *)fieldErrors loadObject:(nonnull MVMCoreLoadObject *)loadObject;

// Calls the default, see LoadHandler.
- (void)loadFinished:(nullable MVMCoreLoadObject *)loadObject loadedViewController:(nullable MFViewController *)loadedViewController error:(nullable MVMCoreErrorObject *)error __attribute__((objc_requires_super));

// By default, does nothing.
- (void)loadCancelled:(nullable MVMCoreLoadObject *)loadObject;

#pragma mark - adobe analytics

// add any addtional track data for the action that is fired with the main action informaiton.
- (nullable NSArray <NSDictionary *> *)additionalActionsToTrackWithMainActionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;

// Returns action track data, it can be overrided for customization
- (nullable NSDictionary *)getActionTrackDataDictionaryForActionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;

// Initiates track page state
- (void)adobeTrackPageState;

// can be subclassed to return any additional data for action tracking
- (nullable NSDictionary *)additionalDataToTrackActionWithActionInformation:(nullable NSDictionary *)actionInformation;

// can be subclassed to return any additional data for page tracking
- (nullable NSDictionary *)additionalDataToTrackForPage;

// can be subclased to return dynamic pagename values for page tracking
- (nullable NSArray *)dynamicPageNameValuesToTrackPage;

#pragma mark - Animation

// main manager used for intro animations
@property (nullable, strong, nonatomic) MVMAnimationManager *introAnimationManager;
// property to check if controller has animations disabled
@property (assign) BOOL disableAnimations;

// subclass to set up intro animations
- (void)setupIntroAnimations;

@end

