import { isNumber } from '../../utils/types';
import { Transition } from '.';
import { getRectFromProps, SharedTransition, SharedTransitionAnimationType } from './shared-transition';
import { ImageSource } from '../../image-source';
import { ContentView } from '../content-view';
import { GridLayout } from '../layouts/grid-layout';
import { Screen } from '../../platform/screen';
import { android as androidUtils } from '../../utils/native-helper';
var SnapshotViewGroup = (function (_super) {
    __extends(SnapshotViewGroup, _super);
    function SnapshotViewGroup(context) {
        var _this = _super.call(this, context) || this;
        return global.__native(_this);
    }
    SnapshotViewGroup.prototype.onMeasure = function () {
        this.setMeasuredDimension(0, 0);
    };
    SnapshotViewGroup.prototype.onLayout = function () {
    };
    return SnapshotViewGroup;
}(android.view.ViewGroup));
class ContentViewSnapshot extends ContentView {
    createNativeView() {
        return new SnapshotViewGroup(this._context);
    }
}
var CustomSpringInterpolator = (function (_super) {
    __extends(CustomSpringInterpolator, _super);
    function CustomSpringInterpolator() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    CustomSpringInterpolator.prototype.getInterpolation = function (input) {
        var res = _super.prototype.getInterpolation.call(this, input) * 1.1;
        if (res > 1) {
            return float(1);
        }
        return float(res);
    };
    return CustomSpringInterpolator;
}(android.view.animation.AnticipateOvershootInterpolator));
var CustomLinearInterpolator = (function (_super) {
    __extends(CustomLinearInterpolator, _super);
    function CustomLinearInterpolator() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    CustomLinearInterpolator.prototype.getInterpolation = function (input) {
        var res = _super.prototype.getInterpolation.call(this, input) * 1.1;
        if (res > 1) {
            return float(1);
        }
        return float(res);
    };
    return CustomLinearInterpolator;
}(android.view.animation.LinearInterpolator));
function setTransitionName(view) {
    if (!view?.sharedTransitionTag) {
        return;
    }
    try {
        androidx.core.view.ViewCompat.setTransitionName(view.nativeView, view.sharedTransitionTag);
    }
    catch (err) {
        // ignore
    }
}
export class PageTransition extends Transition {
    constructor(duration, curve, pageLoadedTimeout = 0) {
        // disable custom curves until we can fix the issue with the animation not completing
        if (curve) {
            console.warn('PageTransition does not support custom curves at the moment. The passed in curve will be ignored.');
        }
        if (typeof duration !== 'number') {
            duration = 500;
        }
        super(duration);
        this.pageLoadedTimeout = pageLoadedTimeout;
    }
    createAndroidAnimator(transitionType) {
        const state = SharedTransition.getState(this.id);
        const pageStart = state.pageStart;
        const startFrame = getRectFromProps(pageStart, {
            x: 0,
            y: 0,
            width: Screen.mainScreen.widthPixels,
            height: Screen.mainScreen.heightPixels,
        });
        const pageEnd = state.pageEnd;
        const endFrame = getRectFromProps(pageEnd);
        const pageReturn = state.pageReturn;
        const returnFrame = getRectFromProps(pageReturn);
        let customDuration = -1;
        if (state.activeType === SharedTransitionAnimationType.present && isNumber(pageEnd?.duration)) {
            customDuration = pageEnd.duration;
        }
        else if (isNumber(state.pageReturn?.duration)) {
            customDuration = state.pageReturn.duration;
        }
        const animationSet = new android.animation.AnimatorSet();
        animationSet.setDuration(customDuration > -1 ? customDuration : this.getDuration());
        const alphaValues = Array.create('float', 2);
        const translationXValues = Array.create('float', 2);
        const translationYValues = Array.create('float', 2);
        switch (transitionType) {
            case Transition.AndroidTransitionType.enter:
                // incoming page (to)
                alphaValues[0] = isNumber(pageStart?.opacity) ? pageStart?.opacity : 0;
                alphaValues[1] = isNumber(pageEnd?.opacity) ? pageEnd?.opacity : 1;
                translationYValues[0] = startFrame.y;
                translationYValues[1] = endFrame.y;
                translationXValues[0] = startFrame.x;
                translationXValues[1] = endFrame.x;
                break;
            case Transition.AndroidTransitionType.exit:
                // current page (from)
                alphaValues[0] = 1;
                alphaValues[1] = 0;
                translationYValues[0] = 0;
                translationYValues[1] = 0;
                break;
            case Transition.AndroidTransitionType.popEnter:
                // current page (returning to)
                alphaValues[0] = 0;
                alphaValues[1] = 1;
                break;
            case Transition.AndroidTransitionType.popExit:
                // removing page (to)
                alphaValues[0] = isNumber(pageEnd?.opacity) ? pageEnd?.opacity : 1;
                alphaValues[1] = isNumber(pageStart?.opacity) ? pageStart?.opacity : 0;
                translationYValues[0] = endFrame.y;
                translationYValues[1] = startFrame.y;
                translationXValues[0] = endFrame.x;
                translationXValues[1] = startFrame.x;
                break;
        }
        const properties = {
            alpha: alphaValues,
            translationX: translationXValues,
            translationY: translationYValues,
        };
        const animations = new java.util.HashSet();
        for (const prop in properties) {
            // console.log(prop, ' ', properties[prop][1]);
            const animator = android.animation.ObjectAnimator.ofFloat(null, prop, properties[prop]);
            if (customDuration) {
                // duration always overrides default spring
                animator.setInterpolator(new CustomLinearInterpolator());
            }
            else {
                animator.setInterpolator(new CustomSpringInterpolator());
            }
            animations.add(animator);
        }
        animationSet.playTogether(animations);
        return animationSet;
    }
    androidFragmentTransactionCallback(fragmentTransaction, currentEntry, newEntry) {
        const fromPage = currentEntry.resolvedPage;
        const toPage = newEntry.resolvedPage;
        const newFragment = newEntry.fragment;
        const state = SharedTransition.getState(this.id);
        if (!state) {
            // when navigating transition is set on the currentEntry but never cleaned up
            // which means that on a next navigation forward (without transition) and back
            // we will go here with an empty state!
            currentEntry.transition = null;
            return;
        }
        const pageEnd = state.pageEnd;
        //we can't look for presented right now as the toPage might not be loaded
        // and thus some views like ListView/Pager... might not have loaded their "children"
        // presented will be handled in loaded event of toPage
        const { presenting } = SharedTransition.getSharedElements(fromPage, toPage);
        // Note: we can enhance android more over time with element targeting across different screens
        // const pageStart = state.pageStart;
        // const pageEndIndependentTags = Object.keys(pageEnd?.sharedTransitionTags || {});
        // console.log('pageEndIndependentTags:', pageEndIndependentTags);
        // for (const tag of pageEndIndependentTags) {
        // 	// only consider start when there's a matching end
        // 	const pageStartIndependentProps = pageStart?.sharedTransitionTags[tag];
        // 	if (pageStartIndependentProps) {
        // 		console.log('pageStartIndependentProps:', tag, pageStartIndependentProps);
        // 	}
        // 	const pageEndIndependentProps = pageEnd?.sharedTransitionTags[tag];
        // 	let independentView = presenting.find((v) => v.sharedTransitionTag === tag);
        // 	let isPresented = false;
        // 	if (!independentView) {
        // 		independentView = presented.find((v) => v.sharedTransitionTag === tag);
        // 		if (!independentView) {
        // 			break;
        // 		}
        // 		isPresented = true;
        // 	}
        // 	if (independentView) {
        // 		console.log('independentView:', independentView);
        // 		const imageSource = renderToImageSource(independentView);
        // 		const image = new Image();
        // 		image.src = imageSource;
        // 		const { hostView } = loadViewInBackground(image);
        // 		(<any>fromPage).addChild(hostView);
        // 		independentView.opacity = 0;
        // 	}
        // }
        const onPageLoaded = () => {
            // add a timeout so that Views like ListView / CollectionView can have their children instantiated
            setTimeout(() => {
                const { presented } = SharedTransition.getSharedElements(fromPage, toPage);
                // const sharedElementTags = sharedElements.map((v) => v.sharedTransitionTag);
                presented.forEach(setTransitionName);
                newFragment.startPostponedEnterTransition();
            }, this.pageLoadedTimeout);
        };
        fragmentTransaction.setReorderingAllowed(true);
        let customDuration = -1;
        if (state.activeType === SharedTransitionAnimationType.present && isNumber(pageEnd?.duration)) {
            customDuration = pageEnd.duration;
        }
        else if (isNumber(state.pageReturn?.duration)) {
            customDuration = state.pageReturn.duration;
        }
        const transitionSet = new androidx.transition.TransitionSet();
        transitionSet.setDuration(customDuration > -1 ? customDuration : this.getDuration());
        transitionSet.addTransition(new androidx.transition.ChangeBounds());
        transitionSet.addTransition(new androidx.transition.ChangeTransform());
        transitionSet.setOrdering(androidx.transition.TransitionSet.ORDERING_TOGETHER);
        if (customDuration) {
            // duration always overrides default spring
            transitionSet.setInterpolator(new CustomLinearInterpolator());
        }
        else {
            transitionSet.setInterpolator(new CustomSpringInterpolator());
        }
        // postpone enter until we call "loaded" on the new page
        newFragment.postponeEnterTransition();
        newFragment.setSharedElementEnterTransition(transitionSet);
        newFragment.setSharedElementReturnTransition(transitionSet);
        // Guard against duplicate shared element names being added to the same transaction
        const addedSharedElementNames = new Set();
        presenting.forEach((v) => {
            const name = v?.sharedTransitionTag;
            const nativeView = v?.nativeView;
            if (!name || !nativeView || addedSharedElementNames.has(name)) {
                // prevent duplicates or invalid items
                return;
            }
            setTransitionName(v);
            try {
                fragmentTransaction.addSharedElement(nativeView, name);
                addedSharedElementNames.add(name);
            }
            catch (err) {
                // ignore duplicates or issues adding shared element to avoid crashing
            }
        });
        if (toPage.isLoaded) {
            onPageLoaded();
        }
        else {
            toPage.once('loaded', onPageLoaded);
        }
    }
}
function renderToImageSource(hostView) {
    const bitmap = android.graphics.Bitmap.createBitmap(hostView.android.getWidth(), hostView.android.getHeight(), android.graphics.Bitmap.Config.ARGB_8888);
    const canvas = new android.graphics.Canvas(bitmap);
    // ensure we start with a blank transparent canvas
    canvas.drawARGB(0, 0, 0, 0);
    hostView.android.draw(canvas);
    return new ImageSource(bitmap);
}
function loadViewInBackground(view) {
    const hiddenHost = new ContentViewSnapshot();
    const hostView = new GridLayout(); // use a host view to ensure margins are respected
    hiddenHost.content = hostView;
    hiddenHost.visibility = 'collapse';
    hostView.addChild(view);
    hiddenHost._setupAsRootView(androidUtils.getApplicationContext());
    hiddenHost.callLoaded();
    androidUtils.getCurrentActivity().addContentView(hiddenHost.android, new android.view.ViewGroup.LayoutParams(0, 0));
    return {
        hiddenHost,
        hostView,
    };
}
//# sourceMappingURL=page-transition.android.js.map