/*
 * Lunar Launcher
 * Copyright (C) 2022 Md Rasel Hossain
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package rasel.lunar.launcher

//import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet

import android.Manifest
import android.annotation.SuppressLint
import android.app.NotificationManager
import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color
import android.location.Location
import android.net.Uri
import android.net.http.SslError
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Environment.isExternalStorageManager
import android.os.Handler
import android.os.Looper
import android.print.PDFPrint
import android.provider.Settings
import android.telephony.TelephonyManager
import android.view.View
import android.view.WindowInsets
import android.view.WindowManager
import android.webkit.JavascriptInterface
import android.webkit.SslErrorHandler
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
import androidx.core.content.FileProvider
import androidx.core.net.toUri
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.google.android.material.color.DynamicColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.apps.AppDrawer
import rasel.lunar.launcher.apps.DismissCalback
import rasel.lunar.launcher.apps.SearchMenu
import rasel.lunar.launcher.databinding.LauncherActivityBinding
import rasel.lunar.launcher.feeds.Feeds
import rasel.lunar.launcher.feeds.WidgetHost
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_FIRST_LAUNCH
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_FIRST_LAUNCH
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import rasel.lunar.launcher.helpers.Constants.Companion.widgetHostId
import rasel.lunar.launcher.helpers.ViewPagerAdapter
import rasel.lunar.launcher.home.LauncherHome
import rasel.lunar.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl
import rasel.lunar.launcher.home.LauncherHome.Companion.listTags
import rasel.lunar.launcher.model.MissD
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.JGuru
import rasel.lunar.launcher.model.jGuruTag
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.model.getT
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.receiver.NLService
import rasel.lunar.launcher.utils.RssList.jGuruMain
import rasel.lunar.launcher.utils.beforeDay
import rasel.lunar.launcher.utils.make0H
import rasel.lunar.launcher.workers.AppInfoGetter
import rasel.lunar.launcher.workers.ArcaGetter
import rasel.lunar.launcher.workers.ClienGetter
import rasel.lunar.launcher.workers.ContactInfoGetter
import rasel.lunar.launcher.workers.DCGetter
import rasel.lunar.launcher.workers.DotaxGetter
import rasel.lunar.launcher.workers.FmKoreaGetter
import rasel.lunar.launcher.workers.NewsFeedsGetter
import rasel.lunar.launcher.workers.OpenWeatherGetter
import rasel.lunar.launcher.workers.RecentCallGetter
import rasel.lunar.launcher.workers.RecentSmsGetter
import rasel.lunar.launcher.workers.RedditGetter
import rasel.lunar.launcher.workers.RuliWebGetter
import rasel.lunar.launcher.workers.TheQooGetter
import rasel.lunar.launcher.workers.WorkersDb
import rasel.lunar.launcher.workers.YoutubeGetter
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.random.Random


internal class LauncherActivity : AppCompatActivity() {

    private lateinit var binding: LauncherActivityBinding
    private lateinit var settingsPrefs: SharedPreferences
    lateinit var viewPager: ViewPager2

    companion object {

        private var mWorkManager: WorkManager? = null
        val SMS_WORK_TAG = "RecentSmsGetter"
        val CALL_WORK_TAG = "MissedCallGetter"
        val FEDDS_WORK_TAG = "NewsFeedsGetter"
        val YT_WORK_TAG = "YoutubeGetter"
        val COMIC_WORK_TAG = "ComicGetter"
        val COMIC2_WORK_TAG = "ComicGetter2"
        val REDDIT_WORK_TAG = "RedditGetter"
        val shortTimePeriod = 20L
        val longTimePeriod = 60L
        val midTimePeriod = 30L
        var isOpendFold = false
        val qDayPeriod = 60L * 8L

        @JvmStatic var lActivity: LauncherActivity? = null
        @JvmStatic var appWidgetManager: AppWidgetManager? = null
        @JvmStatic var appWidgetHost: WidgetHost? = null
        fun refreshDeviceData()
        {
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    SMS_WORK_TAG,
                    ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<RecentSmsGetter>(longTimePeriod, TimeUnit.MINUTES)
                        .addTag(SMS_WORK_TAG)
                        .build())
            }, 500, TimeUnit.MILLISECONDS)
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(RecentCallGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    RecentCallGetter.TAG,
                    ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<RecentCallGetter>(longTimePeriod, TimeUnit.MINUTES)
                        .addTag(RecentCallGetter.TAG)
                        .build())
            }, 500, TimeUnit.MILLISECONDS)

            var delay = 3L
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(ContactInfoGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    ContactInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<ContactInfoGetter>(12, TimeUnit.HOURS)
                        .addTag(ContactInfoGetter.TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay = delay + 3L
//            Executors.newSingleThreadScheduledExecutor().schedule({
//                mWorkManager?.cancelAllWorkByTag(AppInfoGetter.TAG)
//                mWorkManager?.enqueueUniquePeriodicWork(
//                    AppInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
//                    PeriodicWorkRequestBuilder<AppInfoGetter>(12, TimeUnit.HOURS)
//                        .addTag(AppInfoGetter.TAG)
//                        .build())
//            }, delay, TimeUnit.SECONDS)
//            delay = delay + 3L
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.enqueue(OneTimeWorkRequest.from(AppInfoGetter::class.java))
            }, 5, TimeUnit.SECONDS)

        }

        fun refreshFeeds() {
            var delay = 5L
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(FEDDS_WORK_TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    FEDDS_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<NewsFeedsGetter>(shortTimePeriod, TimeUnit.MINUTES)
                        .addTag(FEDDS_WORK_TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(YT_WORK_TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    YT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<YoutubeGetter>(longTimePeriod, TimeUnit.MINUTES)
                        .addTag(YT_WORK_TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(REDDIT_WORK_TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    REDDIT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<RedditGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(REDDIT_WORK_TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(COMIC_WORK_TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    COMIC_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<FmKoreaGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(COMIC_WORK_TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<DotaxGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(COMIC2_WORK_TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(ClienGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    ClienGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<ClienGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(ClienGetter.TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(DCGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    DCGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<DCGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(DCGetter.TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(RuliWebGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    RuliWebGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<RuliWebGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(RuliWebGetter.TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(TheQooGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    TheQooGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<TheQooGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(TheQooGetter.TAG)
                        .build())
            }, delay, TimeUnit.SECONDS)
            delay= delay + 5
            Executors.newSingleThreadScheduledExecutor().schedule({
                mWorkManager?.cancelAllWorkByTag(ArcaGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    ArcaGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<ArcaGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(ArcaGetter.TAG)
                        .build())

            }, delay, TimeUnit.SECONDS)
            Executors.newSingleThreadScheduledExecutor().schedule({
                //de574a260b1f474d99955729241909
                mWorkManager?.cancelAllWorkByTag(OpenWeatherGetter.TAG)
                mWorkManager?.enqueueUniquePeriodicWork(
                    OpenWeatherGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    PeriodicWorkRequestBuilder<OpenWeatherGetter>(midTimePeriod, TimeUnit.MINUTES)
                        .addTag(OpenWeatherGetter.TAG)
                        .build())
            }, 3, TimeUnit.SECONDS)

        }

        fun workmanager() : WorkManager? {
            if (mWorkManager == null && lActivity != null) {
                mWorkManager = WorkManager.getInstance(lActivity!!)
            }
            return mWorkManager
        }

    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)

        BLog.LOGE("onConfigurationChanged Configuration >> ${newConfig}")

        BLog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}")
        isOpendFold = (newConfig?.screenWidthDp?.toInt() ?: 0 > 700) == true
//        binding.viewPager.invalidate()
//        binding.viewPager.currentItem = 1
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)

        BLog.LOGE("onNewIntent intent >> ${intent}")

        intent?.extras?.keySet()?.forEach {
            BLog.LOGE("onNewIntent intent >> ${it}")
        }


//        binding.viewPager.invalidate()
//        binding.viewPager.post {
//            binding.viewPager?.adapter?.notifyDataSetChanged()
//        }
    }

    @SuppressLint("NewApi")
    override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        mWorkManager = WorkManager.getInstance(this)
        DynamicColors.applyToActivityIfAvailable(this)


        settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0)
        AppCompatDelegate.setDefaultNightMode(settingsPrefs.getInt(KEY_APPLICATION_THEME, MODE_NIGHT_FOLLOW_SYSTEM))

        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window, false)
        binding = LauncherActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)

        lActivity = this
        appWidgetManager = AppWidgetManager.getInstance(applicationContext)
        appWidgetHost = WidgetHost(applicationContext, widgetHostId)
        appWidgetHost?.startListening()

        /*  if this is the first launch,
            then remember the event and show the welcome dialog */
        welcomeDialog()
        setupView()

        /* handle navigation back events */
        handleBackPress()

        val cn: ComponentName = ComponentName(this, NLService::class.java)
        val n = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        if (n.isNotificationListenerAccessGranted(cn)) {
        } else {
            val intent = Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
            startActivity(intent)
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (!isExternalStorageManager()) {
                try {
                    startActivityForResult(Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
                        addCategory("android.intent.category.DEFAULT")
                        data = Uri.parse(String.format("package:%s", applicationContext.packageName))
                    }, 300)
                } catch (e: Exception) {
                    startActivityForResult(Intent().apply {
                        action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
                    }, 300)
                }
            }
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        appWidgetHost?.stopListening()
    }

    override fun onStart() {
        super.onStart()
        BLog.LOGE("LauncherActivity onStart()")
        statusBarView()
        setBgColor()
    }

    @RequiresApi(Build.VERSION_CODES.O_MR1)
    override fun onResume() {
        super.onResume()
        BLog.LOGE("LauncherActivity onResume")
    }

    private fun welcomeDialog() {

        var needAsk = if (
            this.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=  PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
        )  {
            true
        } else false


        getSharedPreferences(PREFS_FIRST_LAUNCH, 0).let {
            if (it.getBoolean(KEY_FIRST_LAUNCH, true) || needAsk) {
                it.edit().putBoolean(KEY_FIRST_LAUNCH, false).apply()
                MaterialAlertDialogBuilder(this)
                    .setTitle(R.string.welcome)
                    .setMessage(R.string.welcome_description)
                    .setPositiveButton(R.string.got_it) { dialog, _ ->
                        dialog.dismiss()
                        askPermissions()
                    }.show()
            }
        }

        if (!needAsk) {
            refreshDeviceData()
            refreshFeeds()
        }
    }

    /* ask for the permissions */
    private fun askPermissions() {
        /* phone permission */

        if (
            this.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=  PackageManager.PERMISSION_GRANTED ||
            this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
        ) {
            this.requestPermissions(arrayOf(
                Manifest.permission.READ_CONTACTS,
                Manifest.permission.READ_CALL_LOG,
                Manifest.permission.CALL_PHONE,
                Manifest.permission.READ_SMS,
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.RECEIVE_MMS,
                Manifest.permission.RECEIVE_SMS,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.CALL_PHONE,
                Manifest.permission.READ_SMS), 1)
        }
        /* modify system settings */
        if (!Settings.System.canWrite(this)) {
            this.startActivity(
                Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
                    .setData(Uri.parse("package:" + this.packageName))
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            )
        }
    }

    /* set up viewpager2 */
    private fun setupView() {
        viewPager = binding.viewPager.apply {
            adapter = ViewPagerAdapter(
                supportFragmentManager,
                mutableListOf(Feeds(), LauncherHome(), AppDrawer()),
                lifecycle
            )
            offscreenPageLimit = 1
            setCurrentItem(1, false)
            reduceDragSensitivity()
        }
    }

    private fun setBgColor() {
        binding.root.setBackgroundColor(Color.parseColor("#22000000"))
    }

    private fun statusBarView() {
        if (settingsPrefs.getBoolean(KEY_STATUS_BAR, false)) {
            /* hide status bar */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                window.insetsController?.hide(WindowInsets.Type.statusBars())
            } else {
                @Suppress("DEPRECATION")
                window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
            }
            topPadding(false)
        } else {
            /* show status bar */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                window.insetsController?.show(WindowInsets.Type.statusBars())
            } else {
                @Suppress("DEPRECATION")
                window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            }
            topPadding(true)
        }
    }

    /* alternative of deprecated onBackPressed method */
    private fun handleBackPress() {
        onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                /* while in to-do manager, go back to home screen */
                if (supportFragmentManager.backStackEntryCount != 0) supportFragmentManager.popBackStack()

                /* while in feeds or app drawer, go back to home screen */
                if (viewPager.currentItem != 1) viewPager.currentItem = 1
            }
        })
    }

    private fun topPadding(topPadding: Boolean) {
        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
            windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()).let {
                val topInset = if (topPadding) {
                    if (it.top == 0) windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top
                    else it.top
                } else 0

                view.updatePadding(0, topInset, 0, it.bottom)
            }
            WindowInsetsCompat.CONSUMED
        }
    }

    private fun ViewPager2.reduceDragSensitivity() {
        ViewPager2::class.java.getDeclaredField("mRecyclerView").apply {
            isAccessible = true
        }.let { recyclerViewField ->
            (recyclerViewField.get(this) as RecyclerView).let { recyclerView ->
                RecyclerView::class.java.getDeclaredField("mTouchSlop").apply {
                    isAccessible = true
                    set(recyclerView, this.get(recyclerView) as Int * 8)
                }
            }
        }
    }

    fun openSearchMenus(keyword : String, dismissCalback: DismissCalback) {
        SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()}
    }

    class EndCallReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            BLog.LOGE("EndCallReceiver >>> ${intent}")
            val phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE) ?: return
            if (phoneState == TelephonyManager.EXTRA_STATE_IDLE) {
                refreshDeviceData()
            }
        }
    }
    class SMSReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            BLog.LOGE("SMSReceiver >>> ${intent}")
            refreshDeviceData()
        }
    }

    fun openDrive(gmmIntentUri : Uri, pakage : String? = null) {
        val mapIntent = Intent(Intent.ACTION_MEDIA_SHARED, gmmIntentUri)
        pakage?.let {
            mapIntent.setPackage(pakage)
        }
        startActivity(mapIntent)
    }

    fun doWebSavor(url : String, callBack :CommadCallabck?) {
        if (true)return
        this.callBack = callBack

        binding.searcher01.post { binding.searcher01.visibility = View.VISIBLE }
        BLog.LOGE("binding.otherCheck before ThreadRun")
        binding.searcher01.bringToFront()
        binding.searcher01.alpha = 1f
        binding.searcher01.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                if (url?.contains("missav") == true && isF) {
                    BLog.LOGE("binding.otherCheck before reload")
                    view?.loadUrl(url!!)
                    isF = true
                    return false
                }
                return false
            }

            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}")
                super.onPageStarted(view, url, favicon)
            }
            override fun onReceivedError(
                view: WebView?,
                request: WebResourceRequest?,
                error: WebResourceError?
            ) {

            }
            override fun onReceivedSslError(
                view: WebView?,
                handler: SslErrorHandler?,
                error: SslError?
            ) {
                handler?.proceed()
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                autoScrollDown(view,url)

            }
        }

        WebView.setWebContentsDebuggingEnabled(false)
        binding.searcher01.apply {
            setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정
            setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결
            try {
                settings.apply {
                    userAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
                    javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정
                    loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드
                    useWideViewPort = true // 화면에 맞게 페이지 확대/축소
                    domStorageEnabled = true // DOM 저장소 사용 가능하도록 설정
                    setSupportMultipleWindows(true)
                    javaScriptCanOpenWindowsAutomatically = true // 팝업창 차단 해제
                    cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
                    textZoom = 100 // system 에 의한 글꼴 변형 방지
                    defaultTextEncodingName = "UTF-8" // 인코딩 설정
                    allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부
                    layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정
                }
            } catch (ignore: NoSuchMethodError) {

            }.apply {
                loadUrl(url) // 웹페이지 연결
            }
        }
    }

    fun autoScrollDown(webView:  WebView?, url: String?) {
        webView?.let { webView ->
            val ramdomTimeSec =
                800L.plus(Math.abs(Random(System.currentTimeMillis()).nextLong().rem(489L)))
            BLog.LOGE("ramdomTime >>> ${ramdomTimeSec}")
            if (((webView?.scrollY ?: 0) + (webView?.height
                    ?: 0)) < webView?.contentHeight ?: 0
            ) {
                webView?.postDelayed({
                    webView?.scrollY = (binding.searcher01.scrollY) + (binding.searcher01.height.toFloat() * 0.4).toInt()
                    autoScrollDown(webView, url)
                }, ramdomTimeSec)
            } else {
                webView?.postDelayed({
                    binding.viewPager.bringToFront()
                    binding.searcher01.alpha = 0f
                    if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
                        val fileName = url?.toUri()?.path?.replace("/","_")?.replace(".","_")
                        val path = File(Environment.getExternalStorageDirectory(),"bums")
                        if (path.exists() == false) {
                            path.mkdirs()
                        }
                        val file = File(path, fileName.plus(".pdf"))

                        BLog.LOGE("file >>> ${file.absolutePath}")
                        try {
                            PDFPrint.generatePDFFromWebView(file,webView, object : PDFPrint.OnPDFPrintListener {
                                override fun onSuccess(file: File?) {
                                    BLog.LOGE("file >>>> ${file!!.absolutePath}")
                                    val shareIntent: Intent = Intent().apply {
                                        action = Intent.ACTION_SEND
                                        this.`package` = "com.synology.dsdrive"
                                        val imageUri = FileProvider.getUriForFile(
                                            this@LauncherActivity,
                                            "rasel.lunar.launcher.debug.fileprovider",  //(use your app signature + ".provider" )
                                            file
                                        )
                                        putExtra(Intent.EXTRA_STREAM, imageUri)
                                        type = "pdf"
                                    }
                                    this@LauncherActivity.startActivity(shareIntent)
                                }

                                override fun onError(exception: java.lang.Exception?) {
                                    Toast.makeText(this@LauncherActivity,
                                        "Pdf Save Failk ${exception?.localizedMessage}", Toast.LENGTH_LONG).show()
                                    exception?.printStackTrace()
                                }
                            } )
                        } catch (e: IOException) {
                            e.printStackTrace()
                        }
                    } else {

                    }
                }, ramdomTimeSec)
            }
        }
    }

    var callBack : CommadCallabck? = null
    var isF = false
    fun doWebParseStart(url : String, callBack :CommadCallabck?) {
        isF = false
        this.callBack = callBack
        binding.searcher01.post { binding.searcher01.visibility = View.VISIBLE }
        BLog.LOGE("binding.otherCheck before ThreadRun")
        binding.searcher01.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                if (url?.contains("missav") == true && isF) {
                    BLog.LOGE("binding.otherCheck before reload")
                    view?.loadUrl(url!!)
                    isF = true
                    return false
                }
                return false
            }

            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}")
                super.onPageStarted(view, url, favicon)
            }
            override fun onReceivedError(
                view: WebView?,
                request: WebResourceRequest?,
                error: WebResourceError?
            ) {
//                super.onReceivedError(view, request, error)
            }
            override fun onReceivedSslError(
                view: WebView?,
                handler: SslErrorHandler?,
                error: SslError?
            ) {
                handler?.proceed()
            }



            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                lastedFinishedPageUrl = url ?: ""
                BLog.LOGE("binding.otherCheck searcher01 in onPageFinished ${url}")
                //lastedFinishedPageUrl?.length ?: 0 > 10 &&
//                if(url?.startsWith("https://") == true) {
                if (url?.contains("youtube", false) == true) {
                    view?.evaluateJavascript(
                        "function getAll() {\n" +
                                "           MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
                                "        };getAll()"
                    ) { result ->
                        (result as? String)?.let {

                        }
                    }
                } else if(url?.contains("translate.google.com") == true) {
                    binding.searcher01.postDelayed({
                        binding.searcher01.evaluateJavascript(
                            "function getAll() {\n" +
                                    "           MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
                                    "        };getAll()"
                        ) { result ->
                            (result as? String)?.let {

                            }
                        }
                    }, 6000L)
                } else {
                    //if (url?.contains("guru", true) == true)
                    view?.evaluateJavascript(
                        "function getAll() {\n" +
                                "           MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
                                "        };getAll()"
                    ) { result ->
                        (result as? String)?.let {

                        }
                    }
//                        if (!isF) {
//                            binding.searcher01.post {
//                                binding.searcher01.loadUrl("https://missav.com/dm11/ko")
//                                isF = true
//                            }
//                        }
                }
                if (isF) this@LauncherActivity.callBack?.collectComplete()
//                    binding.searcher01.post { binding.searcher01.visibility = View.GONE }
//                }
            }
        }
        WebView.setWebContentsDebuggingEnabled(false)
        binding.searcher01.apply {
//            Jsoup.connect("https://missav.com/dm11/ko").userAgent()
//                .timeout(30000).get()?.apply {
//                    BLog.LOGE("Jsoup.connect(missAv).get()  ${this}")
//                }
            try {
                this.removeJavascriptInterface("MyJavaScriptInterface")
            }catch (e :Exception) {}
            this.addJavascriptInterface(MyJavaScriptInterface(this),"MyJavaScriptInterface")
            setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정
            setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결
            try {
                settings.apply {
                    userAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
                    javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정
                    loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드
                    useWideViewPort = true // 화면에 맞게 페이지 확대/축소
                    domStorageEnabled = true // DOM 저장소 사용 가능하도록 설정
                    setSupportMultipleWindows(true)
                    javaScriptCanOpenWindowsAutomatically = true // 팝업창 차단 해제
                    cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
                    textZoom = 100 // system 에 의한 글꼴 변형 방지
                    defaultTextEncodingName = "UTF-8" // 인코딩 설정
                    allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부
                    layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정
                }
            } catch (ignore: NoSuchMethodError) {

            }.apply {
                loadUrl(url) // 웹페이지 연결
            }
        }
    }

    var maxDate : Long = Long.MIN_VALUE
    var minDate : Long = Long.MAX_VALUE
    val triple = 1000L * 60L * 60L * 24L * 2L
    val simpldateFormat = SimpleDateFormat("d MMM, yy", Locale.US)
    fun jGuruToday(doc: Document) {
        var temp = arrayListOf<RssData>()
        doc.getElementsByTag("li").forEach {
            if (it.getElementsByTag("img").size > 0) {
                var title = it.getElementsByTag("a").get(0).attr("title")
                var model = title.replace("[", "").split("]")[0]
                var pageLink = it.getElementsByTag("a").get(0).attr("href")
                var imgg = it.getElementsByTag("img").get(0).attr("src")
                var actor = if (it.getElementsByClass("wpptax").size > 0 )it.getElementsByClass("wpptax").get(0).text() else ""
                if (pageLink.length > 0 && imgg.length > 0 && title.length > 0 && model.length > 0) {
                    temp.add(
                        JGuru(
                            model = model,
                            title = title,
                            pageLink = pageLink,
                            image = imgg,
                            tags = actor,
                            date =  beforeDay(Date(),3) + 360000
                        ).getRssData()
                    )
                }
            }
        }.apply {
            this@LauncherActivity.callBack?.collectComplete()
            WorkersDb.insertBulkInteface(temp)
            Toast.makeText(this@LauncherActivity,
                "Stored rank data", Toast.LENGTH_LONG).show()
            binding.searcher01?.post { binding.searcher01.loadUrl(jGuruMain) }
        }
    }
    fun jGuruMain(doc: Document) {
//        BLog.LOGE("SimpleDateFormat D MM yy => ${SimpleDateFormat("d MMM yy", Locale.US).format(Date())}")
        var temp = arrayListOf<RssData>()
        val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href")
        doc.getElementsByClass("column").forEach {
            var title = it.getElementsByAttribute("title").get(0).text()
            var model = title.replace("[","").split("]")[0]
            var pageLink = it.getElementsByClass("imgg").get(0).getElementsByAttribute("href").get(0).attr("href")
            var imgg = it.getElementsByClass("imgg").get(0).getElementsByAttribute("src").get(0).attr("src")
            var tags = it.getElementsByClass("tags").get(0).text()
            var date = it.getElementsByClass("date").get(0).text()
            var regDate = simpldateFormat.parse(date).time

            minDate = Math.min(minDate,regDate)
            maxDate = Math.max(maxDate,regDate)
            temp.add(JGuru(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = make0H(simpldateFormat.parse(date))).getRssData())
        }.apply {
            var itemC = 0
            WorkersDb.insertBulkInteface(temp)
            callBack?.onConsoleLog("Stored data :: ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}")
//            Toast.makeText(this@LauncherActivity,
//                "Stored data :: ${listItem.size} items ::  [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}] \n set in ${itemC}", Toast.LENGTH_LONG).show()
////            }
            binding.searcher01?.post { binding.searcher01.loadData("<html></html>",null,null) }
            this@LauncherActivity.callBack?.collectComplete()
        }
    }

    fun jGuruTag(doc: Document) {
        doc.getElementsByTag("ul").forEach {
            it.children().forEach {
                if (it.tag().name.contains("li")) {
                    listTags.add(
                        jGuruTag(
                            tagTitle = it.getElementsByTag("a").get(0).text(),
                            link = it.getElementsByTag("a").get(0).attr("href")
                        )
                    )

                }
            }
        }.apply {
//            listTags.sortByDescending { it.pubDate() }
//            Toast.makeText(this@LauncherActivity,
//                "Stored data :: ${listTags.size}tags", Toast.LENGTH_SHORT).show()
            binding.searcher01?.post { binding.searcher01.loadData("<html></html>",null,null) }
            this@LauncherActivity.callBack?.collectComplete()
        }
    }

    inner class MyJavaScriptInterface(val webView: WebView) {


        @JavascriptInterface
        fun sendValueFromHtml(result: String) {
//            BLog.LOGE("binding.otherCheck start with ${result}")
            if (lastedFinishedPageUrl.contains(jGuruMain)) {
                var htmlString = result.replace("\\u003","<")
                val doc: Document = Jsoup.parse(htmlString)
                if (lastedFinishedPageUrl?.contains("page") == true || lastedFinishedPageUrl?.equals(
                        jGuruMain
                    ) == true
                ) {
                    jGuruMain(doc)
                } else if (lastedFinishedPageUrl?.contains("/most-watched-rank") == true) {
                    jGuruToday(doc)
                } else if (lastedFinishedPageUrl?.contains("/tags/") == true) {
                    jGuruTag(doc)
                }
            } else if (lastedFinishedPageUrl?.contains("youtube") == true) {
//                val doc: Document = Jsoup.parse(result)
//                ytChannel(doc)
            } else if (lastedFinishedPageUrl?.contains("missav")==true) {
                val doc: Document = Jsoup.parse(result)
//                BLog.LOGE("missav >>> ${doc}")
                var temp = arrayListOf<RssData>()
                doc.getElementsByClass("thumbnail group").forEach { miss_li ->
                    if (miss_li.getElementsByTag("img").size > 0 && miss_li.getElementsByTag("img").get(0).attr("data-src").length > 10 &&
                        miss_li.getElementsByTag("img").get(0).attr("data-src").startsWith("https") &&
                        miss_li.getElementsByTag("img").get(0).attr("data-src").endsWith("jpg")) {
                        var link = if(miss_li.getElementsByTag("a").size > 0) miss_li.getElementsByTag("a").get(0).attr("href") else ""
                        var title =  miss_li.getElementsByClass("text-secondary group-hover:text-primary").getT()
                        var thumb =  miss_li.getElementsByTag("img").get(0).attr("data-src")
                        var desc =  miss_li.getElementsByTag("img").get(0).text()
                        MissD().apply {
                            this.link = link
                            this.title = title
                            this.thumb = thumb
                            this.desc = desc
                            temp.add(this.getRssData())
                        }
                    }
                }.apply {
                    WorkersDb.insertBulkData(temp)
//                    BLog.LOGE("temp >>> ${temp.size}")
//                    binding.searcher01?.post { binding.searcher01.loadData("<html></html>",null,null) }
                }

            } else if(lastedFinishedPageUrl?.contains("javmost")==true){
                val doc: Document = Jsoup.parse(result)
                callBack?.onConsoleLog("${lastedFinishedPageUrl} >>> ${doc.title()}")
                doc.getElementsByClass("card").forEach { card ->
                    callBack?.onConsoleLog("${lastedFinishedPageUrl}_card >>> ${card}")
                    var model = if(card.getElementsByTag("img").size > 0) card.getElementsByTag("img").get(0).attr("src") else ""
                    var thumb = if(card.getElementsByTag("img").size > 0) card.getElementsByTag("img").get(0).attr("alt") else ""
                    var title = ""
                    var date = ""
                    if(card.getElementsByClass("card-block").size > 0) if(card.getElementsByClass("card-block").size > 0) {
                        title = card.getElementsByClass("card-block").get(0).getElementsByTag("a").get(0).attr("title")
                        date  = card.getElementsByTag("span").get(0).text()
                    }

                    callBack?.onConsoleLog("" +
                            "model >>>>> ${model}\n" +
                            "thumb >>>>> ${thumb}\n" +
                            "title >>>>> ${title}\n" +
                            "date >>>>> ${date}" +
                            "")
                }
            } else if(lastedFinishedPageUrl?.contains("https://translate.google.com") == true){
                callBackHandler.removeCallbacks(postNext)
                val doc: Document = Jsoup.parse(result)
                doc.getElementsByTag("span").forEach { span ->
//                                BLog.LOGE("on getHangule ${span.text()}")
                    if(span.hasAttr("jsaction") &&
                        span.attr("jsaction").contains("mouseout") &&
                        span.attr("jsaction").contains("contextmenu") &&
                        span.attr("jsaction").contains("click") &&
                        span.attr("jsaction").contains("mouseover")
                    ) {
                        BLog.LOGE("on getHangule $span")
                        val resultString = span.text()
                        if (resultString != null && resultString.length > 0) {
                            callBackHandler.removeCallbacks(postNext)
                            callBack?.onConsoleLog("result::${span.text()}")
                            callBack = null
                        }
                    }
                }.apply {
                    callBackHandler.removeCallbacks(postNext)
                    callBackHandler.postDelayed(postNext,25000L)
                }
            } else {
                val doc: Document = Jsoup.parse(result)
                callBack?.onConsoleLog("lastedFinishedPageUrl >>> ${doc}")
            }
            BLog.LOGE("binding.otherCheck after ThreadRun")
        }

    }
    var postNext : Runnable = Runnable{
            callBack?.collectComplete()
    }

    val callBackHandler = Handler(Looper.getMainLooper())

}





fun beforeDay(date: Date): Long {
    val cal: Calendar = Calendar.getInstance()
    cal.setTime(date)
    cal.add(Calendar.DAY_OF_YEAR, -2)
    cal.add(Calendar.HOUR, 8)
    return cal.timeInMillis
}

interface CommadCallabck  {
    fun onConsoleLog(log : String)
    fun collectComplete()
}

fun openNews(schemeString : String) {
    val gmmIntentUri = Uri.parse(schemeString)
    val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
    mapIntent.setPackage("com.android.chrome")
    lActivity?.startActivity(mapIntent)
}


fun openYouTube(schemeString : String) {
    val gmmIntentUri = Uri.parse(schemeString)
    val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
    mapIntent.setPackage("com.google.android.youtube")
    lActivity?.startActivity(mapIntent)
}

fun openReddit(schemeString : String) {
    val gmmIntentUri = Uri.parse(schemeString)
    val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
    mapIntent.setPackage("com.reddit.frontpage")
    lActivity?.startActivity(mapIntent)
}

fun openDotax(schemeString : String) {
    val gmmIntentUri = Uri.parse(schemeString)
    val mapIntent = Intent(Intent.ACTION_VIEW)
    mapIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
    mapIntent.addCategory(Intent.CATEGORY_BROWSABLE)
    mapIntent.setPackage("net.daum.android.cafe")
    mapIntent.setData(gmmIntentUri)
    lActivity?.startActivity(mapIntent)
}


fun openOpera(schemeString : String) {
    BLog.LOGE("openOpera ${schemeString}")
    val gmmIntentUri = Uri.parse(schemeString)
    val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
    mapIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
    mapIntent.setPackage("com.opera.browser")
    lActivity?.startActivity(mapIntent)
}

