import { ActionItemBase, ActionBarBase, isVisible, flatProperty, iosIconRenderingModeProperty, traceMissingIcon, iosLargeTitleProperty } from './action-bar-common';
import { View } from '../core/view';
import { Color } from '../../color';
import { ios as iosBackground } from '../styling/background';
import { LinearGradient } from '../styling/linear-gradient';
import { colorProperty, backgroundInternalProperty, backgroundColorProperty, backgroundImageProperty } from '../styling/style-properties';
import { ios as iosViewUtils } from '../utils';
import { ImageSource } from '../../image-source';
import { layout, isFontIconURI } from '../../utils';
import { SDK_VERSION } from '../../utils/constants';
import { accessibilityHintProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityValueProperty } from '../../accessibility/accessibility-properties';
export * from './action-bar-common';
const UNSPECIFIED = layout.makeMeasureSpec(0, layout.UNSPECIFIED);
function loadActionIcon(item) {
    let is = null;
    let img = null;
    const itemIcon = item.icon;
    const itemStyle = item.style;
    if (isFontIconURI(itemIcon)) {
        const fontIconCode = itemIcon.split('//')[1];
        const font = itemStyle.fontInternal;
        const color = itemStyle.color;
        is = ImageSource.fromFontIconCodeSync(fontIconCode, font, color);
    }
    else {
        is = ImageSource.fromFileOrResourceSync(itemIcon);
    }
    if (is && is.ios) {
        img = is.ios;
    }
    else {
        traceMissingIcon(itemIcon);
    }
    return img;
}
var TapBarItemHandlerImpl = (function (_super) {
    __extends(TapBarItemHandlerImpl, _super);
    function TapBarItemHandlerImpl() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TapBarItemHandlerImpl.initWithOwner = function (owner) {
        var handler = TapBarItemHandlerImpl.new();
        handler._owner = owner;
        return handler;
    };
    TapBarItemHandlerImpl.prototype.tap = function (args) {
        var _a;
        var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
        if (owner) {
            owner._raiseTap();
        }
    };
    TapBarItemHandlerImpl.ObjCExposedMethods = {
        tap: { returns: interop.types.void, params: [interop.types.id] },
    };
    return TapBarItemHandlerImpl;
}(NSObject));
export class ActionItem extends ActionItemBase {
    constructor() {
        super(...arguments);
        this._ios = {
            position: 'left',
            systemIcon: undefined,
        };
    }
    // @ts-ignore
    get ios() {
        return this._ios;
    }
    set ios(value) {
        throw new Error('ActionItem.ios is read-only');
    }
}
export class NavigationButton extends ActionItem {
    _onVisibilityChanged(visibility) {
        if (this._navigationItem) {
            const visible = visibility === 'visible';
            this._navigationItem.setHidesBackButtonAnimated(!visible, true);
        }
    }
}
export class ActionBar extends ActionBarBase {
    get ios() {
        const page = this.page;
        if (!page || !page.parent) {
            return;
        }
        const viewController = page.ios;
        return viewController?.navigationController?.navigationBar;
    }
    [accessibilityValueProperty.setNative](value) {
        value = value == null ? null : `${value}`;
        this.nativeViewProtected.accessibilityValue = value;
        const navigationItem = this._getNavigationItem();
        if (navigationItem) {
            navigationItem.accessibilityValue = value;
        }
    }
    [accessibilityLabelProperty.setNative](value) {
        value = value == null ? null : `${value}`;
        this.nativeViewProtected.accessibilityLabel = value;
        const navigationItem = this._getNavigationItem();
        if (navigationItem) {
            navigationItem.accessibilityLabel = value;
        }
    }
    [accessibilityHintProperty.setNative](value) {
        value = value == null ? null : `${value}`;
        this.nativeViewProtected.accessibilityHint = value;
        const navigationItem = this._getNavigationItem();
        if (navigationItem) {
            navigationItem.accessibilityHint = value;
        }
    }
    [accessibilityLanguageProperty.setNative](value) {
        value = value == null ? null : `${value}`;
        this.nativeViewProtected.accessibilityLanguage = value;
        const navigationItem = this._getNavigationItem();
        if (navigationItem) {
            navigationItem.accessibilityLanguage = value;
        }
    }
    createNativeView() {
        return this.ios;
    }
    disposeNativeView() {
        const navBar = this.navBar;
        if (navBar?.gradientLayer) {
            navBar.gradientLayer = null;
        }
        super.disposeNativeView();
    }
    _addChildFromBuilder(name, value) {
        if (value instanceof NavigationButton) {
            this.navigationButton = value;
        }
        else if (value instanceof ActionItem) {
            this.actionItems?.addItem(value);
        }
        else if (value instanceof View) {
            this.titleView = value;
        }
    }
    get _getActualSize() {
        const nativeView = this.ios;
        if (!nativeView) {
            return { width: 0, height: 0 };
        }
        const frame = nativeView.frame;
        const size = frame.size;
        const width = layout.toDevicePixels(size.width);
        const height = layout.toDevicePixels(size.height);
        return { width, height };
    }
    layoutInternal() {
        const { width, height } = this._getActualSize;
        const widthSpec = layout.makeMeasureSpec(width, layout.EXACTLY);
        const heightSpec = layout.makeMeasureSpec(height, layout.EXACTLY);
        this.measure(widthSpec, heightSpec);
        this.layout(0, 0, width, height, false);
    }
    _getIconRenderingMode() {
        switch (this.iosIconRenderingMode) {
            case 'alwaysOriginal':
                return 1 /* UIImageRenderingMode.AlwaysOriginal */;
            case 'alwaysTemplate':
                return 2 /* UIImageRenderingMode.AlwaysTemplate */;
            case 'automatic':
            default:
                return 1 /* UIImageRenderingMode.AlwaysOriginal */;
        }
    }
    _getNavigationItem() {
        const page = this.page;
        // Page should be attached to frame to update the action bar.
        if (!page || !page.frame) {
            return null;
        }
        const viewController = page.ios;
        return viewController.navigationItem;
    }
    update() {
        const page = this.page;
        // Page should be attached to frame to update the action bar.
        if (!page || !page.frame) {
            return;
        }
        const viewController = page.ios;
        // visionOS may init with different nav stack setup
        if (!viewController) {
            return;
        }
        const navigationItem = viewController.navigationItem;
        const navController = viewController.navigationController;
        if (!navController) {
            return;
        }
        const navigationBar = navController.navigationBar;
        let previousController;
        // Set Title
        navigationItem.title = this.title;
        const titleView = this.titleView;
        if (titleView && titleView.ios) {
            navigationItem.titleView = titleView.ios;
        }
        else {
            navigationItem.titleView = null;
        }
        // Find previous ViewController in the navigation stack
        const indexOfViewController = navController.viewControllers.indexOfObject(viewController);
        if (indexOfViewController > 0 && indexOfViewController < navController.viewControllers.count) {
            previousController = navController.viewControllers[indexOfViewController - 1];
        }
        // Set back button text
        if (previousController) {
            if (this.navigationButton) {
                const tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(this.navigationButton));
                const barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(this.navigationButton.text + '', 0 /* UIBarButtonItemStyle.Plain */, tapHandler, 'tap');
                previousController.navigationItem.backBarButtonItem = barButtonItem;
            }
            else {
                previousController.navigationItem.backBarButtonItem = null;
            }
        }
        // Set back button image
        let img;
        if (this.navigationButton && isVisible(this.navigationButton) && this.navigationButton.icon) {
            img = loadActionIcon(this.navigationButton);
        }
        // TODO: This could cause issue when canceling BackEdge gesture - we will change the backIndicator to
        // show the one from the old page but the new page will still be visible (because we canceled EdgeBackSwipe gesutre)
        // Consider moving this to new method and call it from - navigationControllerDidShowViewControllerAnimated.
        const image = img ? img.imageWithRenderingMode(1 /* UIImageRenderingMode.AlwaysOriginal */) : null;
        if (SDK_VERSION >= 15) {
            const appearance = this._getAppearance(navigationBar);
            appearance.setBackIndicatorImageTransitionMaskImage(image, image);
            this._updateAppearance(navigationBar, appearance);
        }
        else {
            navigationBar.backIndicatorImage = image;
            navigationBar.backIndicatorTransitionMaskImage = image;
        }
        // Set back button visibility
        if (this.navigationButton) {
            this.navigationButton._navigationItem = navigationItem;
            navigationItem.setHidesBackButtonAnimated(!isVisible(this.navigationButton), false);
        }
        // Populate action items
        this.populateMenuItems(navigationItem);
        // update colors explicitly - they may have to be cleared form a previous page
        this.updateFills(navigationBar);
        // the 'flat' property may have changed in between pages
        this.updateFlatness(navigationBar);
        if (!this.isLayoutValid) {
            this.layoutInternal();
        }
        // Make sure accessibility values are up-to-date on the navigationItem
        navigationItem.accessibilityValue = this.accessibilityValue;
        navigationItem.accessibilityLabel = this.accessibilityLabel;
        navigationItem.accessibilityLanguage = this.accessibilityLanguage;
        navigationItem.accessibilityHint = this.accessibilityHint;
        // Configure large title support for this navigation item
        this.checkLargeTitleSupport(navigationItem);
    }
    populateMenuItems(navigationItem) {
        const items = this.actionItems?.getVisibleItems() ?? [];
        const leftBarItems = NSMutableArray.new();
        const rightBarItems = NSMutableArray.new();
        for (let i = 0; i < items.length; i++) {
            const barButtonItem = this.createBarButtonItem(items[i]);
            if (items[i].ios.position === 'left') {
                leftBarItems.addObject(barButtonItem);
            }
            else {
                rightBarItems.insertObjectAtIndex(barButtonItem, 0);
            }
        }
        navigationItem.setLeftBarButtonItemsAnimated(leftBarItems, false);
        navigationItem.setRightBarButtonItemsAnimated(rightBarItems, false);
        if (leftBarItems.count > 0) {
            navigationItem.leftItemsSupplementBackButton = true;
        }
    }
    createBarButtonItem(item) {
        const tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(item));
        // associate handler with menuItem or it will get collected by JSC.
        item.handler = tapHandler;
        let barButtonItem;
        if (item.actionView && item.actionView.ios) {
            const recognizer = UITapGestureRecognizer.alloc().initWithTargetAction(tapHandler, 'tap');
            item.actionView.ios.addGestureRecognizer(recognizer);
            barButtonItem = UIBarButtonItem.alloc().initWithCustomView(item.actionView.ios);
        }
        else if (item.ios.systemIcon !== undefined) {
            let id = item.ios.systemIcon;
            if (typeof id === 'string') {
                id = parseInt(id);
            }
            barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(id, tapHandler, 'tap');
        }
        else if (item.icon) {
            const img = loadActionIcon(item);
            if (img) {
                const image = img.imageWithRenderingMode(this._getIconRenderingMode());
                barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(image, 0 /* UIBarButtonItemStyle.Plain */, tapHandler, 'tap');
            }
        }
        else {
            barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(item.text + '', 0 /* UIBarButtonItemStyle.Plain */, tapHandler, 'tap');
        }
        if (item.text) {
            barButtonItem.isAccessibilityElement = true;
            barButtonItem.accessibilityLabel = item.text;
            barButtonItem.accessibilityTraits = UIAccessibilityTraitButton;
        }
        return barButtonItem;
    }
    updateFills(navBar) {
        const color = this.color;
        this.setColor(navBar, color);
        this._setBackgroundColor(navBar, this.style.backgroundColor);
        this._createBackgroundUIImage(navBar, this.style.backgroundImage, (image) => {
            this._setBackgroundImage(navBar, image);
        });
    }
    setColor(navBar, color) {
        if (!navBar) {
            return;
        }
        if (color) {
            const titleTextColor = NSDictionary.dictionaryWithObjectForKey(color.ios, NSForegroundColorAttributeName);
            if (SDK_VERSION >= 15) {
                const appearance = this._getAppearance(navBar);
                appearance.titleTextAttributes = titleTextColor;
            }
            navBar.titleTextAttributes = titleTextColor;
            navBar.largeTitleTextAttributes = titleTextColor;
            navBar.tintColor = color.ios;
        }
        else {
            navBar.titleTextAttributes = null;
            navBar.largeTitleTextAttributes = null;
            navBar.tintColor = null;
        }
    }
    _setBackgroundColor(navBar, color) {
        if (!navBar) {
            return;
        }
        const nativeColor = color instanceof Color ? color.ios : color;
        if (__VISIONOS__ || SDK_VERSION >= 15) {
            const appearance = this._getAppearance(navBar);
            // appearance.configureWithOpaqueBackground();
            appearance.backgroundColor = nativeColor;
            this._updateAppearance(navBar, appearance);
        }
        else {
            // legacy styling
            navBar.barTintColor = nativeColor;
        }
    }
    _getBackgroundColor(navBar) {
        if (!navBar) {
            return null;
        }
        let color;
        if (__VISIONOS__ || SDK_VERSION >= 15) {
            const appearance = this._getAppearance(navBar);
            color = appearance.backgroundColor;
        }
        else {
            // legacy styling
            color = navBar.barTintColor;
        }
        return color;
    }
    _setBackgroundImage(navBar, image) {
        if (!navBar) {
            return;
        }
        if (__VISIONOS__ || SDK_VERSION >= 15) {
            const appearance = this._getAppearance(navBar);
            // appearance.configureWithOpaqueBackground();
            appearance.backgroundImage = image;
            this._updateAppearance(navBar, appearance);
        }
        else {
            // legacy styling
            // Set a blank image in case image is null and flatness is enabled
            if (this.flat && !image) {
                image = UIImage.new();
            }
            navBar.setBackgroundImageForBarMetrics(image, 0 /* UIBarMetrics.Default */);
        }
    }
    _getBackgroundImage(navBar) {
        if (!navBar) {
            return null;
        }
        let image;
        if (__VISIONOS__ || SDK_VERSION >= 15) {
            const appearance = this._getAppearance(navBar);
            image = appearance.backgroundImage;
        }
        else {
            // legacy styling
            image = navBar.backgroundImageForBarMetrics(0 /* UIBarMetrics.Default */);
        }
        return image;
    }
    _createBackgroundUIImage(navBar, value, callback) {
        if (!navBar) {
            return;
        }
        if (value) {
            if (value instanceof LinearGradient) {
                if (!navBar.gradientLayer) {
                    navBar.gradientLayer = CAGradientLayer.new();
                }
                iosViewUtils.drawGradient(navBar, navBar.gradientLayer, value);
                const renderer = UIGraphicsImageRenderer.alloc().initWithSize(navBar.bounds.size);
                const img = renderer.imageWithActions((context) => {
                    navBar.gradientLayer.renderInContext(context.CGContext);
                });
                callback(img);
                // Return here to avoid unnecessary cleanups
                return;
            }
            // Background image
            iosBackground.createUIImageFromURI(this, value, false, callback);
        }
        else {
            callback(null);
        }
        if (navBar.gradientLayer) {
            navBar.gradientLayer = null;
        }
    }
    _onTitlePropertyChanged() {
        const page = this.page;
        if (!page) {
            return;
        }
        console.log('ActionBar._onTitlePropertyChanged', this.title);
        if (page.frame) {
            page.frame._updateActionBar(page);
        }
        const navigationItem = page.ios.navigationItem;
        navigationItem.title = this.title;
    }
    updateFlatness(navBar) {
        if (this.flat) {
            if (SDK_VERSION >= 15) {
                const appearance = this._getAppearance(navBar);
                appearance.shadowColor = UIColor.clearColor;
                this._updateAppearance(navBar, appearance);
            }
            else {
                // Do not apply blank image if background image is already set
                if (!this.backgroundImage) {
                    navBar.setBackgroundImageForBarMetrics(UIImage.new(), 0 /* UIBarMetrics.Default */);
                }
                navBar.shadowImage = UIImage.new();
                navBar.translucent = false;
            }
        }
        else {
            if (SDK_VERSION >= 15) {
                if (navBar.standardAppearance) {
                    // Not flat and never been set do nothing.
                    const appearance = navBar.standardAppearance;
                    appearance.shadowColor = this.iosShadow ? UINavigationBarAppearance.new().shadowColor : UIColor.clearColor;
                    this._updateAppearance(navBar, appearance);
                }
            }
            else {
                // Do not apply blank image if background image is already set
                if (!this.backgroundImage) {
                    // Bar metrics is needed even when unsetting the image
                    navBar.setBackgroundImageForBarMetrics(null, 0 /* UIBarMetrics.Default */);
                }
                navBar.shadowImage = null;
                navBar.translucent = true;
            }
        }
    }
    _getAppearance(navBar) {
        return navBar.standardAppearance ?? UINavigationBarAppearance.new();
    }
    _updateAppearance(navBar, appearance) {
        navBar.standardAppearance = appearance;
        navBar.compactAppearance = appearance;
        navBar.scrollEdgeAppearance = appearance;
    }
    onMeasure(widthMeasureSpec, heightMeasureSpec) {
        const width = layout.getMeasureSpecSize(widthMeasureSpec);
        const height = layout.getMeasureSpecSize(heightMeasureSpec);
        if (this.titleView) {
            View.measureChild(this, this.titleView, UNSPECIFIED, UNSPECIFIED);
        }
        this.actionItems?.getItems().forEach((actionItem) => {
            const actionView = actionItem.actionView;
            if (actionView) {
                View.measureChild(this, actionView, UNSPECIFIED, UNSPECIFIED);
            }
        });
        // We ignore our width/height, minWidth/minHeight dimensions because it is against Apple policy to change height of NavigationBar.
        this.setMeasuredDimension(width, height);
    }
    onLayout(left, top, right, bottom) {
        const titleView = this.titleView;
        if (titleView) {
            if (SDK_VERSION > 10) {
                // On iOS 11 titleView is wrapped in another view that is centered with constraints.
                View.layoutChild(this, titleView, 0, 0, titleView.getMeasuredWidth(), titleView.getMeasuredHeight());
            }
            else {
                // On iOS <11 titleView is direct child of UINavigationBar so we give it full width and leave
                // the layout to center it.
                View.layoutChild(this, titleView, 0, 0, right - left, bottom - top);
            }
        }
        this.actionItems?.getItems().forEach((actionItem) => {
            const actionView = actionItem.actionView;
            if (actionView && actionView.ios) {
                const measuredWidth = actionView.getMeasuredWidth();
                const measuredHeight = actionView.getMeasuredHeight();
                View.layoutChild(this, actionView, 0, 0, measuredWidth, measuredHeight);
            }
        });
        super.onLayout(left, top, right, bottom);
    }
    layoutNativeView(left, top, right, bottom) {
        return;
    }
    get navBar() {
        // Page should be attached to frame to update the action bar.
        if (this.page?.frame?.ios?.controller) {
            return this.page.frame.ios.controller.navigationBar;
        }
        return null;
    }
    [colorProperty.getDefault]() {
        return null;
    }
    [colorProperty.setNative](color) {
        const navBar = this.navBar;
        this.setColor(navBar, color);
    }
    [backgroundColorProperty.getDefault]() {
        return this._getBackgroundColor(this.navBar);
    }
    [backgroundColorProperty.setNative](color) {
        this._setBackgroundColor(this.navBar, color);
    }
    [backgroundImageProperty.getDefault]() {
        return this._getBackgroundImage(this.navBar);
    }
    [backgroundImageProperty.setNative](value) {
        const navBar = this.navBar;
        this._createBackgroundUIImage(navBar, value, (image) => {
            this._setBackgroundImage(navBar, image);
        });
    }
    [backgroundInternalProperty.getDefault]() {
        return null;
    }
    // @ts-ignore
    [backgroundInternalProperty.setNative](value) { }
    [flatProperty.setNative](value) {
        const navBar = this.navBar;
        if (navBar) {
            this.updateFlatness(navBar);
        }
    }
    [iosIconRenderingModeProperty.getDefault]() {
        return 'alwaysOriginal';
    }
    [iosIconRenderingModeProperty.setNative](value) {
        this.update();
    }
    [iosLargeTitleProperty.setNative](value) {
        if (!this.navBar) {
            return;
        }
        if (SDK_VERSION >= 11) {
            this.navBar.prefersLargeTitles = value;
        }
    }
    checkLargeTitleSupport(navigationItem) {
        const navBar = this.navBar;
        if (!navBar) {
            return;
        }
        // Configure large title display mode only when not using a custom titleView
        if (SDK_VERSION >= 11) {
            if (this.iosLargeTitle) {
                // Always show large title for this navigation item when large titles are enabled
                navigationItem.largeTitleDisplayMode = 1 /* UINavigationItemLargeTitleDisplayMode.Always */;
            }
            else {
                if (SDK_VERSION >= 26) {
                    // Explicitly disable large titles for this navigation item
                    // Due to overlapping title issue in iOS 26
                    navigationItem.largeTitleDisplayMode = 2 /* UINavigationItemLargeTitleDisplayMode.Never */;
                }
                else {
                    navigationItem.largeTitleDisplayMode = 0 /* UINavigationItemLargeTitleDisplayMode.Automatic */;
                }
            }
        }
    }
}
//# sourceMappingURL=index.ios.js.map