// Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import <UIKit/UIKit.h>

#import "MaterialElevation.h"

API_DEPRECATED_BEGIN(
    "🕘 Schedule time to migrate. "
    "Use branded UINavigationController instead: go/material-ios-top-app-bars/gm2-migration. "
    "This is go/material-ios-migrations#not-scriptable 🕘",
    ios(11, 12))

@protocol MDCButtonBarDelegate;

/** Specifies the title alignment of the |MDCNavigationBar|. */
typedef NS_ENUM(NSInteger, MDCNavigationBarTitleAlignment) {
  /** Aligns the title to the center of the NavigationBar. */
  MDCNavigationBarTitleAlignmentCenter,
  /** Aligns the title to the left/leading of the NavigationBar. */
  MDCNavigationBarTitleAlignmentLeading
};

/**
 Behaviors that affect the layout of an |MDCNavigationBar|'s titleView.
 */

typedef NS_ENUM(NSInteger, MDCNavigationBarTitleViewLayoutBehavior) {
  /**
   The title view's width will equal the navigation bar's width minus any space consumed by the
   leading and trailing buttons.

   The title view's center may not align with the navigation bar's center in this case.
   */
  MDCNavigationBarTitleViewLayoutBehaviorFill,

  /**
   Align the title view's center with the navigation bar's center, if possible.
   */
  MDCNavigationBarTitleViewLayoutBehaviorCenter,

  /**
   Align the title view's center with the navigation bar's center, if possible. Relies on the title
   view's intrinsicContentSize to determine its width.
   */
  MDCNavigationBarTitleViewLayoutBehaviorCenterFit
};

/**
 This protocol defines all of the properties on UINavigationItem that can be listened to by
 MDCNavigationBar.
 */

@protocol MDCUINavigationItemObservables <NSObject>
@required

@property(nonatomic, copy, nullable) NSString *title;
@property(nonatomic, strong, nullable) UIView *titleView;
@property(nonatomic) BOOL hidesBackButton;
@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leftBarButtonItems;
@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *rightBarButtonItems;
@property(nonatomic) BOOL leftItemsSupplementBackButton;
@property(nonatomic, strong, nullable) UIBarButtonItem *leftBarButtonItem;
@property(nonatomic, strong, nullable) UIBarButtonItem *rightBarButtonItem;

@end

@class MDCNavigationBar;

/**
  The MDCNavigationBarTextColorAccessibilityMutator class creates an external object with which to
  work on an instance of a Material Navigation Bar to activate and ensure accessibility on its title
  and buttons.

  ### Dependencies

  Material NavigationBarTextColorAccessibilityMutator depends on the Navigation Bar material
  component and MDFTextAccessibility Framework.
  */

@interface MDCNavigationBarTextColorAccessibilityMutator : NSObject

/**
 Initializes and returns a newly created accessibility mutator
 */
- (nonnull instancetype)init;

/**
  Mutates title text color and navigation items' tint colors based on background color of
  navigation bar.
  */
- (void)mutate:(nonnull MDCNavigationBar *)navBar;

@end

/**
 The MDCNavigationBar class is a view consisting of a leading and trailing button bar, title label,
 and an optional title view.

 This view is not designed to have subviews added to it except via through its declared properties
 (e.g. titleView).
 */
IB_DESIGNABLE
@interface MDCNavigationBar : UIView <MDCElevatable, MDCElevationOverriding>

#pragma mark Behavior

/* Title displayed in the bar if titleView is unset. */
@property(nonatomic, copy, nullable) NSString *title;

/**
 The title view layout differs from the traditional behavior of UINavigationBar.

 Due to MDCNavigationBar being able to expand vertically, the titleView's height is updated to match
 any changes in the MDCNavigationBar's height.

 You may wish to create a container view that is able to manage subview layout if your situation
 requires it.
 */
@property(nonatomic, strong, nullable) UIView *titleView;

/**
 The behavior that determines how to position the title view.

 By default this is MDCNavigationBarTitleViewLayoutBehaviorFill.
 */
@property(nonatomic) MDCNavigationBarTitleViewLayoutBehavior titleViewLayoutBehavior;

/**
 The horizontal insets that the MDCNavigationBar uses for both the title and titleView. In
 right-to-left the titleInset.left will be used for the right side and the titleInset.right will be
 used for the left side.

 If titleAlignment is center, defaults to UIEdgeInsets(0, 16, 0, 16).
 If titleAlignment is leading and there are no items, defaults to UIEdgeInsets(0, 16, 0, 16).
 If titleAlignment is leading and there are leading & trailing items, defaults to UIEdgeInsetsZero.
 If titleAlignment is leading and there are only trailing items, defaults to
 UIEdgeInsets(0, 16, 0, 0).
 If titleAlignment is leading and there are only leading items, defaults to
 UIEdgeInsets(0, 0, 0, 16).
 */
@property(nonatomic, assign) UIEdgeInsets titleInsets;

/**
 The font applied to the title of navigation bar.
 Font size is enforced to 20.
 Both Default and null_resettable value is MDCTypography's titleFont.
 Note that the font attribute of titleTextAttributes will take precedence over this property.
 */
@property(nonatomic, strong, null_resettable) UIFont *titleFont;

/**
 A behavioral flag that affects whether titleFont can be set to a font of any size or not.

 If enabled, titleFont can be set to a font of any size.

 If disabled, titleFont's size will be adjusted to 20 regardless of the provided font size.

 We intend to enable this property by default in the future and to remote this flag entirely.
 Consider enabling this flag on your navigation bar instances.

 Default is NO.
 */
@property(nonatomic) BOOL allowAnyTitleFontSize;

/**
 The title label's text color.

 Default is nil (text draws black).
 */
@property(nonatomic, strong, nullable) UIColor *titleTextColor;

/**
 The rippleColor that is used for all buttons in trailing and leading button bars.

 If set to nil, button bar buttons use default ripple color.
 */
@property(nonatomic, strong, nullable) UIColor *rippleColor;

/**
 By setting this property to @c YES, the Ripple component will be used instead of Ink
 to display visual feedback to the user.

 @note This property will eventually be enabled by default, deprecated, and then deleted as part
 of our migration to Ripple. Learn more at
 https://github.com/material-components/material-components-ios/tree/develop/components/Ink#migration-guide-ink-to-ripple

 Defaults to NO.
 */
@property(nonatomic, assign) BOOL enableRippleBehavior;

/**
 If true, all button titles will be converted to uppercase.

 Changing this property to NO will update the current title string for all buttons.

 Default is YES.
 */
@property(nonatomic) BOOL uppercasesButtonTitles;

/**
 Sets the title font for the given state for all buttons.

 @param font The font that should be displayed on text buttons for the given state.
 @param state The state for which the font should be displayed.
 */
- (void)setButtonsTitleFont:(nullable UIFont *)font forState:(UIControlState)state;

/**
 Returns the font set for @c state that was set by setButtonsTitleFont:forState:.

 If no font has been set for a given state, the returned value will fall back to the value
 set for UIControlStateNormal.

 @param state The state for which the font should be returned.
 @return The font associated with the given state.
 */
- (nullable UIFont *)buttonsTitleFontForState:(UIControlState)state;

/**
 Sets the title label color for the given state for all buttons.

 @param color The color that should be used on text buttons labels for the given state.
 @param state The state for which the color should be used.
 */
- (void)setButtonsTitleColor:(nullable UIColor *)color forState:(UIControlState)state;

/**
 The tint color applied to the bar items on the leading side of the BottomAppBar. If unset, then
 defaults to using this Navigation Bar's @c tintColor.
 */
@property(nullable, nonatomic, strong) UIColor *leadingBarItemsTintColor;

/**
 The tint color applied to the bar items on the trailing side of the BottomAppBar. If unset, then
 defaults to using this NavigationBar's @c tintColor.
 */
@property(nullable, nonatomic, strong) UIColor *trailingBarItemsTintColor;

/**
 Returns the color set for @c state that was set by setButtonsTitleColor:forState:.

 If no value has been set for a given state, the returned value will fall back to the value
 set for UIControlStateNormal.

 @param state The state for which the color should be returned.
 @return The color associated with the given state.
 */
- (nullable UIColor *)buttonsTitleColorForState:(UIControlState)state;

/** The back button to be displayed, if any. */
@property(nonatomic, strong, nullable) UIBarButtonItem *backItem;

/*  If YES, this navigation bar will hide the back button. */
@property(nonatomic) BOOL hidesBackButton;

/* Use these properties to set multiple items in a navigation bar.
 The single properties (leadingBarButtonItem and trailingBarButtonItem) refer to the first item in
 the respective array of items.

 NOTE: You'll achieve the best results if you use either the singular properties or the plural
 properties consistently and don't try to mix them.

   leadingBarButtonItems are placed in the navigation bar from the leading edge to the trailing edge
 with the first item in the list at the leading outside edge and leading aligned.
   trailingBarButtonItems are placed from the trailing edge to the leading edge with the first item
 in the list at the trailing outside edge and trailing aligned.
 */
@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leadingBarButtonItems;
@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *trailingBarButtonItems;

/* By default, the leadingItemsSupplementBackButton property is NO. In this case, the back button is
 not drawn and the leading item or items replace it. If you would like the leading items to appear
 in addition to the back button (as opposed to instead of it) set leadingItemsSupplementBackButton
 to YES.
 */
@property(nonatomic) BOOL leadingItemsSupplementBackButton;

/*
 Use these when you want to display a custom leading or trailing item in this navigation bar.
 A custom leading item replaces the regular back button unless you set
 leadingItemsSupplementBackButton to YES.
 */
@property(nonatomic, strong, nullable) UIBarButtonItem *leadingBarButtonItem;
@property(nonatomic, strong, nullable) UIBarButtonItem *trailingBarButtonItem;

/**
 Returns the rect of the leading item's view within the given @c coordinateSpace.

 If the provided item is not contained in @c leadingBarButtonItems, then the behavior is undefined.

 @param item The item within @c leadingBarButtonItems whose rect should be computed.
 @param coordinateSpace The coordinate space the returned rect should be in relation to.
 */
- (CGRect)rectForLeadingBarButtonItem:(nonnull UIBarButtonItem *)item
                    inCoordinateSpace:(nonnull id<UICoordinateSpace>)coordinateSpace
    NS_SWIFT_NAME(rect(forLeading:in:));

/**
 Returns the rect of the trailing item's view within the given @c coordinateSpace.

 If the provided item is not contained in @c trailingBarButtonItems, then the behavior is undefined.

 @param item The item within @c trailingBarButtonItems whose rect should be computed.
 @param coordinateSpace The coordinate space the returned rect should be in relation to.
 */
- (CGRect)rectForTrailingBarButtonItem:(nonnull UIBarButtonItem *)item
                     inCoordinateSpace:(nonnull id<UICoordinateSpace>)coordinateSpace
    NS_SWIFT_NAME(rect(forTrailing:in:));

/**
 The horizontal text alignment of the navigation bar title. Defaults to
 MDCNavigationBarTitleAlignmentLeading.
 */
@property(nonatomic) MDCNavigationBarTitleAlignment titleAlignment;

/**
 A block that is invoked when the NavigationBar receives a call to @c
 traitCollectionDidChange:. The block is called after the call to the superclass.
 */
@property(nonatomic, copy, nullable) void (^traitCollectionDidChangeBlock)(
    MDCNavigationBar *_Nonnull navigationBar, UITraitCollection *_Nullable previousTraitCollection);

#pragma mark Observing UINavigationItem instances

/**
 Begin observing changes to the provided navigation item.

 Only one navigation item instance can be observed at a time. Observing a second navigation item
 will stop observation of the first navigation item.

 Once execution returns from this method the receiver's state will match that of the newly-observed
 navigation item.

 The observed navigation item is strongly held.
 */
- (void)observeNavigationItem:(nonnull UINavigationItem *)navigationItem;

/**
 Stop observing changes to the previously-observed navigation item.

 Does nothing if no navigation item is being observed.
 */
- (void)unobserveNavigationItem;

#pragma mark UINavigationItem interface matching

/* Equivalent to leadingBarButtonItems. */
@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leftBarButtonItems;

/* Equivalent to trailingBarButtonItems. */
@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *rightBarButtonItems;

/* Equivalent to leadingBarButtonItem. */
@property(nonatomic, strong, nullable) UIBarButtonItem *leftBarButtonItem;

/* Equivalent to trailingBarButtonItem. */
@property(nonatomic, strong, nullable) UIBarButtonItem *rightBarButtonItem;

/* Equivalent to leadingItemsSupplementBackButton. */
@property(nonatomic) BOOL leftItemsSupplementBackButton;

@end

@interface MDCNavigationBar (ToBeDeprecated)

/**
 The inkColor that is used for all buttons in trailing and leading button bars.

 If set to nil, button bar buttons use default ink color.
 @warning This method will eventually be deprecated. Opt-in to Ripple by setting
 enableRippleBehavior to YES, and then use rippleColor instead. Learn more at
 https://github.com/material-components/material-components-ios/tree/develop/components/Ink#migration-guide-ink-to-ripple
 */
@property(nonatomic, strong, nullable) UIColor *inkColor;

/**
 Display attributes for the titleView's title text.

 Font attribute will take precedence over titleFont property.
 Setting this property will render an NSAttributedString with the assigned attributes across the
 entire text.

 Note: this property will be deprecated in future, please use titleFont and titleTextColor instead.
 */
@property(nonatomic, copy, nullable)
    NSDictionary<NSAttributedStringKey, id> *titleTextAttributes UI_APPEARANCE_SELECTOR;

@end

API_DEPRECATED_END
