import { profile } from '../profiling';
import { isEmbedded } from '../ui/embedding';
import { ApplicationCommon } from './application-common';
let BroadcastReceiver_;
function initBroadcastReceiver() {
    if (BroadcastReceiver_) {
        return BroadcastReceiver_;
    }
    var BroadcastReceiverImpl = /** @class */ (function (_super) {
    __extends(BroadcastReceiverImpl, _super);
    function BroadcastReceiverImpl(onReceiveCallback) {
        var _this = _super.call(this) || this;
        _this._onReceiveCallback = onReceiveCallback;
        return global.__native(_this);
    }
    BroadcastReceiverImpl.prototype.onReceive = function (context, intent) {
        if (this._onReceiveCallback) {
            this._onReceiveCallback(context, intent);
        }
    };
    return BroadcastReceiverImpl;
}(android.content.BroadcastReceiver));
    BroadcastReceiver_ = BroadcastReceiverImpl;
    return BroadcastReceiver_;
}
let NativeScriptLifecycleCallbacks_;
function initNativeScriptLifecycleCallbacks() {
    if (NativeScriptLifecycleCallbacks_) {
        return NativeScriptLifecycleCallbacks_;
    }
    var NativeScriptLifecycleCallbacksImpl = /** @class */ (function (_super) {
    __extends(NativeScriptLifecycleCallbacksImpl, _super);
    function NativeScriptLifecycleCallbacksImpl() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.activitiesCount = 0;
        return _this;
    }
    NativeScriptLifecycleCallbacksImpl.prototype.onActivityCreated = function (activity, savedInstanceState) {
        // console.log('NativeScriptLifecycleCallbacks onActivityCreated');
        this.setThemeOnLaunch(activity);
        if (!Application.android.startActivity) {
            Application.android.setStartActivity(activity);
        }
        if (!this.nativescriptActivity && 'isNativeScriptActivity' in activity) {
            this.nativescriptActivity = activity;
        }
        this.notifyActivityCreated(activity, savedInstanceState);
        if (Application.hasListeners(Application.displayedEvent)) {
            this.subscribeForGlobalLayout(activity);
        }
    };
    NativeScriptLifecycleCallbacksImpl.prototype.onActivityDestroyed = function (activity) {
        // console.log('NativeScriptLifecycleCallbacks onActivityDestroyed');
        if (activity === Application.android.foregroundActivity) {
            Application.android.setForegroundActivity(undefined);
        }
        if (activity === this.nativescriptActivity) {
            this.nativescriptActivity = undefined;
        }
        if (activity === Application.android.startActivity) {
            Application.android.setStartActivity(undefined);
            // Fallback for start activity when it is destroyed but we have a known nativescript activity
            if (this.nativescriptActivity) {
                Application.android.setStartActivity(this.nativescriptActivity);
            }
        }
        Application.android.notify({
            eventName: Application.android.activityDestroyedEvent,
            object: Application.android,
            activity: activity,
        });
        // TODO: This is a temporary workaround to force the V8's Garbage Collector, which will force the related Java Object to be collected.
        gc();
    };
    NativeScriptLifecycleCallbacksImpl.prototype.onActivityPaused = function (activity) {
        // console.log('NativeScriptLifecycleCallbacks onActivityPaused');
        if ('isNativeScriptActivity' in activity) {
            Application.setSuspended(true, {
                // todo: deprecate event.android in favor of event.activity
                android: activity,
                activity: activity,
            });
        }
        Application.android.notify({
            eventName: Application.android.activityPausedEvent,
            object: Application.android,
            activity: activity,
        });
    };
    NativeScriptLifecycleCallbacksImpl.prototype.onActivityResumed = function (activity) {
        // console.log('NativeScriptLifecycleCallbacks onActivityResumed');
        Application.android.setForegroundActivity(activity);
        // NOTE: setSuspended(false) is called in frame/index.android.ts inside onPostResume
        // This is done to ensure proper timing for the event to be raised
        Application.android.notify({
            eventName: Application.android.activityResumedEvent,
            object: Application.android,
            activity: activity,
        });
    };
    NativeScriptLifecycleCallbacksImpl.prototype.onActivitySaveInstanceState = function (activity, bundle) {
        // console.log('NativeScriptLifecycleCallbacks onActivitySaveInstanceState');
        Application.android.notify({
            eventName: Application.android.saveActivityStateEvent,
            object: Application.android,
            activity: activity,
            bundle: bundle,
        });
    };
    NativeScriptLifecycleCallbacksImpl.prototype.onActivityStarted = function (activity) {
        // console.log('NativeScriptLifecycleCallbacks onActivityStarted');
        this.activitiesCount++;
        if (this.activitiesCount === 1) {
            Application.android.setInBackground(false, {
                // todo: deprecate event.android in favor of event.activity
                android: activity,
                activity: activity,
            });
        }
        Application.android.notify({
            eventName: Application.android.activityStartedEvent,
            object: Application.android,
            activity: activity,
        });
    };
    NativeScriptLifecycleCallbacksImpl.prototype.onActivityStopped = function (activity) {
        // console.log('NativeScriptLifecycleCallbacks onActivityStopped');
        this.activitiesCount--;
        if (this.activitiesCount === 0) {
            Application.android.setInBackground(true, {
                // todo: deprecate event.android in favor of event.activity
                android: activity,
                activity: activity,
            });
        }
        Application.android.notify({
            eventName: Application.android.activityStoppedEvent,
            object: Application.android,
            activity: activity,
        });
    };
    NativeScriptLifecycleCallbacksImpl.prototype.setThemeOnLaunch = function (activity) {
        // Set app theme after launch screen was used during startup
        var activityInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), android.content.pm.PackageManager.GET_META_DATA);
        if (activityInfo.metaData) {
            var setThemeOnLaunch = activityInfo.metaData.getInt('SET_THEME_ON_LAUNCH', -1);
            if (setThemeOnLaunch !== -1) {
                activity.setTheme(setThemeOnLaunch);
            }
        }
    };
    NativeScriptLifecycleCallbacksImpl.prototype.notifyActivityCreated = function (activity, bundle) {
        Application.android.notify({
            eventName: Application.android.activityCreatedEvent,
            object: Application.android,
            activity: activity,
            bundle: bundle,
        });
    };
    NativeScriptLifecycleCallbacksImpl.prototype.subscribeForGlobalLayout = function (activity) {
        var rootView = activity.getWindow().getDecorView().getRootView();
        // store the listener not to trigger GC collection before collecting the method
        global.onGlobalLayoutListener = new android.view.ViewTreeObserver.OnGlobalLayoutListener({
            onGlobalLayout: function () {
                Application.android.notify({
                    eventName: Application.displayedEvent,
                    object: Application,
                    android: Application.android,
                    activity: activity,
                });
                var viewTreeObserver = rootView.getViewTreeObserver();
                viewTreeObserver.removeOnGlobalLayoutListener(global.onGlobalLayoutListener);
            },
        });
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(global.onGlobalLayoutListener);
    };
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11;
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_c = typeof androidx !== "undefined" && (_a = androidx.appcompat) !== void 0 && (_b = _a.app) !== void 0 && _b.AppCompatActivity) === "function" ? _c : Object, typeof (_e = typeof android !== "undefined" && (_d = android.os) !== void 0 && _d.Bundle) === "function" ? _e : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivityCreated", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_h = typeof androidx !== "undefined" && (_f = androidx.appcompat) !== void 0 && (_g = _f.app) !== void 0 && _g.AppCompatActivity) === "function" ? _h : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivityDestroyed", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_l = typeof androidx !== "undefined" && (_j = androidx.appcompat) !== void 0 && (_k = _j.app) !== void 0 && _k.AppCompatActivity) === "function" ? _l : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivityPaused", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_p = typeof androidx !== "undefined" && (_m = androidx.appcompat) !== void 0 && (_o = _m.app) !== void 0 && _o.AppCompatActivity) === "function" ? _p : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivityResumed", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_s = typeof androidx !== "undefined" && (_q = androidx.appcompat) !== void 0 && (_r = _q.app) !== void 0 && _r.AppCompatActivity) === "function" ? _s : Object, typeof (_u = typeof android !== "undefined" && (_t = android.os) !== void 0 && _t.Bundle) === "function" ? _u : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivitySaveInstanceState", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_x = typeof androidx !== "undefined" && (_v = androidx.appcompat) !== void 0 && (_w = _v.app) !== void 0 && _w.AppCompatActivity) === "function" ? _x : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivityStarted", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_0 = typeof androidx !== "undefined" && (_y = androidx.appcompat) !== void 0 && (_z = _y.app) !== void 0 && _z.AppCompatActivity) === "function" ? _0 : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "onActivityStopped", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_3 = typeof androidx !== "undefined" && (_1 = androidx.appcompat) !== void 0 && (_2 = _1.app) !== void 0 && _2.AppCompatActivity) === "function" ? _3 : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "setThemeOnLaunch", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_6 = typeof androidx !== "undefined" && (_4 = androidx.appcompat) !== void 0 && (_5 = _4.app) !== void 0 && _5.AppCompatActivity) === "function" ? _6 : Object, typeof (_8 = typeof android !== "undefined" && (_7 = android.os) !== void 0 && _7.Bundle) === "function" ? _8 : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "notifyActivityCreated", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_11 = typeof androidx !== "undefined" && (_9 = androidx.appcompat) !== void 0 && (_10 = _9.app) !== void 0 && _10.AppCompatActivity) === "function" ? _11 : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptLifecycleCallbacksImpl.prototype, "subscribeForGlobalLayout", null);
    NativeScriptLifecycleCallbacksImpl = __decorate([
        JavaProxy('org.nativescript.NativeScriptLifecycleCallbacks')
    ], NativeScriptLifecycleCallbacksImpl);
    return NativeScriptLifecycleCallbacksImpl;
}(android.app.Application.ActivityLifecycleCallbacks));
    NativeScriptLifecycleCallbacks_ = NativeScriptLifecycleCallbacksImpl;
    return NativeScriptLifecycleCallbacks_;
}
let NativeScriptComponentCallbacks_;
function initNativeScriptComponentCallbacks() {
    if (NativeScriptComponentCallbacks_) {
        return NativeScriptComponentCallbacks_;
    }
    var NativeScriptComponentCallbacksImpl = /** @class */ (function (_super) {
    __extends(NativeScriptComponentCallbacksImpl, _super);
    function NativeScriptComponentCallbacksImpl() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    NativeScriptComponentCallbacksImpl.prototype.onLowMemory = function () {
        gc();
        java.lang.System.gc();
        Application.notify({
            eventName: Application.lowMemoryEvent,
            object: Application,
            android: this,
        });
    };
    NativeScriptComponentCallbacksImpl.prototype.onTrimMemory = function (level) {
        // TODO: This is skipped for now, test carefully for OutOfMemory exceptions
    };
    NativeScriptComponentCallbacksImpl.prototype.onConfigurationChanged = function (newConfiguration) {
        Application.android.onConfigurationChanged(newConfiguration);
    };
    var _a, _b, _c;
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", []),
        __metadata("design:returntype", void 0)
    ], NativeScriptComponentCallbacksImpl.prototype, "onLowMemory", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Number]),
        __metadata("design:returntype", void 0)
    ], NativeScriptComponentCallbacksImpl.prototype, "onTrimMemory", null);
    __decorate([
        profile,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [typeof (_c = typeof android !== "undefined" && (_a = android.content) !== void 0 && (_b = _a.res) !== void 0 && _b.Configuration) === "function" ? _c : Object]),
        __metadata("design:returntype", void 0)
    ], NativeScriptComponentCallbacksImpl.prototype, "onConfigurationChanged", null);
    NativeScriptComponentCallbacksImpl = __decorate([
        JavaProxy('org.nativescript.NativeScriptComponentCallbacks')
    ], NativeScriptComponentCallbacksImpl);
    return NativeScriptComponentCallbacksImpl;
}(android.content.ComponentCallbacks2));
    NativeScriptComponentCallbacks_ = NativeScriptComponentCallbacksImpl;
    return NativeScriptComponentCallbacks_;
}
export class AndroidApplication extends ApplicationCommon {
    constructor() {
        super(...arguments);
        this.activityCreatedEvent = AndroidApplication.activityCreatedEvent;
        this.activityDestroyedEvent = AndroidApplication.activityDestroyedEvent;
        this.activityStartedEvent = AndroidApplication.activityStartedEvent;
        this.activityPausedEvent = AndroidApplication.activityPausedEvent;
        this.activityResumedEvent = AndroidApplication.activityResumedEvent;
        this.activityStoppedEvent = AndroidApplication.activityStoppedEvent;
        this.saveActivityStateEvent = AndroidApplication.saveActivityStateEvent;
        this.activityResultEvent = AndroidApplication.activityResultEvent;
        this.activityBackPressedEvent = AndroidApplication.activityBackPressedEvent;
        this.activityNewIntentEvent = AndroidApplication.activityNewIntentEvent;
        this.activityRequestPermissionsEvent = AndroidApplication.activityRequestPermissionsEvent;
        this._registeredReceivers = {};
        this._pendingReceiverRegistrations = new Array();
    }
    init(nativeApp) {
        if (this.nativeApp === nativeApp) {
            return;
        }
        if (this.nativeApp) {
            throw new Error('Application.android already initialized.');
        }
        this._nativeApp = nativeApp;
        this._context = nativeApp.getApplicationContext();
        this._packageName = nativeApp.getPackageName();
        // we store those callbacks and add a function for clearing them later so that the objects will be eligable for GC
        this.lifecycleCallbacks = new (initNativeScriptLifecycleCallbacks())();
        this.nativeApp.registerActivityLifecycleCallbacks(this.lifecycleCallbacks);
        this.componentCallbacks = new (initNativeScriptComponentCallbacks())();
        this.nativeApp.registerComponentCallbacks(this.componentCallbacks);
        this._registerPendingReceivers();
    }
    _registerPendingReceivers() {
        this._pendingReceiverRegistrations.forEach((func) => func(this.context));
        this._pendingReceiverRegistrations.length = 0;
    }
    onConfigurationChanged(configuration) {
        this.setOrientation(this.getOrientationValue(configuration));
        this.setSystemAppearance(this.getSystemAppearanceValue(configuration));
    }
    getNativeApplication() {
        let nativeApp = this.nativeApp;
        if (nativeApp) {
            return nativeApp;
        }
        // Try getting it from module - check whether application.android.init has been explicitly called
        // check whether the com.tns.NativeScriptApplication type exists
        if (com.tns.NativeScriptApplication) {
            nativeApp = com.tns.NativeScriptApplication.getInstance();
        }
        if (!nativeApp && isEmbedded()) {
            nativeApp = com.tns.embedding.ApplicationHolder.getInstance();
        }
        // the getInstance might return null if com.tns.NativeScriptApplication exists but is not the starting app type
        if (!nativeApp) {
            // TODO: Should we handle the case when a custom application type is provided and the user has not explicitly initialized the application module?
            const clazz = java.lang.Class.forName('android.app.ActivityThread');
            if (clazz) {
                const method = clazz.getMethod('currentApplication', null);
                if (method) {
                    nativeApp = method.invoke(null, null);
                }
            }
        }
        // we cannot work without having the app instance
        if (!nativeApp) {
            throw new Error("Failed to retrieve native Android Application object. If you have a custom android.app.Application type implemented make sure that you've called the 'Application.android.init' method.");
        }
        return nativeApp;
    }
    get nativeApp() {
        return this._nativeApp;
    }
    run(entry) {
        if (this.started) {
            throw new Error('Application is already started.');
        }
        this.started = true;
        this.mainEntry = typeof entry === 'string' ? { moduleName: entry } : entry;
        if (!this.nativeApp) {
            const nativeApp = this.getNativeApplication();
            this.init(nativeApp);
        }
    }
    get startActivity() {
        return this._startActivity;
    }
    get foregroundActivity() {
        return this._foregroundActivity;
    }
    setStartActivity(value) {
        this._startActivity = value;
    }
    setForegroundActivity(value) {
        this._foregroundActivity = value;
    }
    get paused() {
        return this.suspended;
    }
    get backgrounded() {
        return this.inBackground;
    }
    get context() {
        return this._context;
    }
    get packageName() {
        return this._packageName;
    }
    registerBroadcastReceiver(intentFilter, onReceiveCallback) {
        const registerFunc = (context) => {
            const receiver = new (initBroadcastReceiver())(onReceiveCallback);
            context.registerReceiver(receiver, new android.content.IntentFilter(intentFilter));
            this._registeredReceivers[intentFilter] = receiver;
        };
        if (this.context) {
            registerFunc(this.context);
        }
        else {
            this._pendingReceiverRegistrations.push(registerFunc);
        }
    }
    unregisterBroadcastReceiver(intentFilter) {
        const receiver = this._registeredReceivers[intentFilter];
        if (receiver) {
            this.context.unregisterReceiver(receiver);
            this._registeredReceivers[intentFilter] = undefined;
            delete this._registeredReceivers[intentFilter];
        }
    }
    getRegisteredBroadcastReceiver(intentFilter) {
        return this._registeredReceivers[intentFilter];
    }
    getRootView() {
        const activity = this.foregroundActivity || this.startActivity;
        if (!activity) {
            return undefined;
        }
        const callbacks = activity['_callbacks'];
        return callbacks ? callbacks.getRootView() : undefined;
    }
    resetRootView(entry) {
        super.resetRootView(entry);
        const activity = this.foregroundActivity || this.startActivity;
        if (!activity) {
            throw new Error('Cannot find android activity.');
        }
        // this.mainEntry = typeof entry === 'string' ? { moduleName: entry } : entry;
        const callbacks = activity['_callbacks'];
        if (!callbacks) {
            throw new Error('Cannot find android activity callbacks.');
        }
        callbacks.resetActivityContent(activity);
    }
    getSystemAppearance() {
        const resources = this.context.getResources();
        const configuration = resources.getConfiguration();
        return this.getSystemAppearanceValue(configuration);
    }
    // https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#configuration_changes
    getSystemAppearanceValue(configuration) {
        const systemAppearance = configuration.uiMode & android.content.res.Configuration.UI_MODE_NIGHT_MASK;
        switch (systemAppearance) {
            case android.content.res.Configuration.UI_MODE_NIGHT_YES:
                return 'dark';
            case android.content.res.Configuration.UI_MODE_NIGHT_NO:
            case android.content.res.Configuration.UI_MODE_NIGHT_UNDEFINED:
                return 'light';
        }
    }
    getOrientation() {
        const resources = this.context.getResources();
        const configuration = resources.getConfiguration();
        return this.getOrientationValue(configuration);
    }
    getOrientationValue(configuration) {
        const orientation = configuration.orientation;
        switch (orientation) {
            case android.content.res.Configuration.ORIENTATION_LANDSCAPE:
                return 'landscape';
            case android.content.res.Configuration.ORIENTATION_PORTRAIT:
                return 'portrait';
            default:
                return 'unknown';
        }
    }
    get android() {
        // ensures Application.android is defined when running on Android
        return this;
    }
}
AndroidApplication.activityCreatedEvent = 'activityCreated';
AndroidApplication.activityDestroyedEvent = 'activityDestroyed';
AndroidApplication.activityStartedEvent = 'activityStarted';
AndroidApplication.activityPausedEvent = 'activityPaused';
AndroidApplication.activityResumedEvent = 'activityResumed';
AndroidApplication.activityStoppedEvent = 'activityStopped';
AndroidApplication.saveActivityStateEvent = 'saveActivityState';
AndroidApplication.activityResultEvent = 'activityResult';
AndroidApplication.activityBackPressedEvent = 'activityBackPressed';
AndroidApplication.activityNewIntentEvent = 'activityNewIntent';
AndroidApplication.activityRequestPermissionsEvent = 'activityRequestPermissions';
export * from './application-common';
export const Application = new AndroidApplication();
export const iOSApplication = undefined;
//# sourceMappingURL=application.android.js.map