package com.droideve.apps.dealify.activities;

import android.Manifest;
import android.app.ActivityManager;
import android.app.Dialog;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.FragmentTransaction;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.droideve.apps.dealify.AppController;
import com.droideve.apps.dealify.R;
import com.droideve.apps.dealify.Services.BusMessage;
import com.droideve.apps.dealify.Services.LocationChangedEvent;
import com.droideve.apps.dealify.Services.NotifyDataNotificationEvent;
import com.droideve.apps.dealify.appconfig.AppConfig;
import com.droideve.apps.dealify.appconfig.Constances;
import com.droideve.apps.dealify.classes.Notification;
import com.droideve.apps.dealify.controllers.SettingsController;
import com.droideve.apps.dealify.controllers.categories.CategoryController;
import com.droideve.apps.dealify.controllers.users.UserController;
import com.droideve.apps.dealify.dtmessenger.MessengerHelper;
import com.droideve.apps.dealify.fragments.MainFragment;
import com.droideve.apps.dealify.fragments.SearchDialog;
import com.droideve.apps.dealify.load_manager.ViewManager;
import com.droideve.apps.dealify.navigationdrawer.NavigationDrawerFragment;
import com.droideve.apps.dealify.network.VolleySingleton;
import com.droideve.apps.dealify.network.api_request.ApiRequest;
import com.droideve.apps.dealify.network.api_request.ApiRequestListeners;
import com.droideve.apps.dealify.network.api_request.SimpleRequest;
import com.droideve.apps.dealify.parser.Parser;
import com.droideve.apps.dealify.parser.api_parser.CategoryParser;
import com.droideve.apps.dealify.parser.tags.Tags;
import com.droideve.apps.dealify.utils.BadgeNotificationUtils;
import com.droideve.apps.dealify.utils.CommunApiCalls;
import com.droideve.apps.dealify.utils.NSLog;
import com.droideve.apps.dealify.utils.NSToast;
import com.droideve.apps.dealify.utils.Session;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Status;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.widget.Autocomplete;
import com.google.android.libraries.places.widget.AutocompleteActivity;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.mikepenz.actionitembadge.library.ActionItemBadge;
import com.mikepenz.community_material_typeface_library.CommunityMaterial;
import com.mikepenz.iconics.IconicsDrawable;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONException;
import org.json.JSONObject;

import butterknife.BindView;
import butterknife.ButterKnife;

import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
import static com.droideve.apps.dealify.appconfig.AppConfig.APP_DEBUG;

import java.util.Map;

public class MainActivity extends GlobalActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, MainFragment.Listener {

    public static final int REQUEST_CHECK_SETTINGS = 0x1;
    public static final int REQUEST_CHECK_SETTINGS_MAIN = 0x2;
    public static int height = 0;
    public static int width = 0;
    public static Menu mainMenu;
    private static boolean opened = false;
    public ViewManager mViewManager;

    Toolbar toolbar;
    @BindView(R.id.toolbar_title)
    TextView toolbarTitle;
    @BindView(R.id.toolbar_subtitle)
    TextView toolbarDescription;
    @BindView(R.id.main_container)
    LinearLayout mainContainer;
    private Session session;
    private FirebaseAnalytics mFirebaseAnalytics;

    /**********************************************/

    //init request http
    private RequestQueue queue;


    /************   EVENT ALERT *******************/


    public static boolean isOpend() {
        return opened;
    }

    public static int getScreenWidth() {
        return Resources.getSystem().getDisplayMetrics().widthPixels;
    }


    public static boolean isAppInForeground(Context context) {
        ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
        ActivityManager.getMyMemoryState(appProcessInfo);
        if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE) {
            return true;
        }
        KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
        // App is foreground, but screen is locked, so show notification
        return km.inKeyguardRestrictedInputMode();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        opened = false;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppController.changeLanguage(this);
        setContentView(R.layout.main_activity);
        ButterKnife.bind(this);

        setupToolbar();

        setupViewManager();

        initGlobalObj();

        loadCategoriesApiCall();

        setupMainFragment();

        screenLayoutSize();

        //check user session and validity
        UserController.checkUserConnection(this);

        //check and request notification permission
        requestNotificationPermission();

        //hide toolbar
        hide_default_toolbar();
    }

    private void setupMainFragment() {

        MainFragment frag = new MainFragment();
        frag.setListener(this);

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        //transaction.setCustomAnimations(R.animator.fade_in_listoffres, R.animator.fade_out_listoffres);

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.main_container, frag, MainFragment.TAG);
        //transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

    private void initGlobalObj() {

        Display display = getWindowManager().getDefaultDisplay();
        width = getScreenWidth();
        height = display.getHeight();

        //Initialize web service API
        queue = VolleySingleton.getInstance(this).getRequestQueue();
        // Obtain the FirebaseAnalytics instance.
        mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);

        //get notification count
        CommunApiCalls.countUnseenNotifications(getApplicationContext());
    }

    private void setupViewManager() {
        mViewManager = new ViewManager(this);
        mViewManager.setLoadingLayout(findViewById(R.id.loading));
        mViewManager.setResultLayout(findViewById(R.id.content_my_store));
        mViewManager.setErrorLayout(findViewById(R.id.error));
        mViewManager.setEmpty(findViewById(R.id.empty));
        mViewManager.showResult();
    }

    private void screenLayoutSize() {
        int size = (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK);

        switch (size) {

            case Configuration.SCREENLAYOUT_SIZE_XLARGE:


            case Configuration.SCREENLAYOUT_SIZE_LARGE:


                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                NavigationDrawerFragment fragNDF = new NavigationDrawerFragment();

                FragmentTransaction transactionNDF = getSupportFragmentManager().beginTransaction();
                //transaction.setCustomAnimations(R.animator.fade_in_listoffres, R.animator.fade_out_listoffres);

                // Replace whatever is in the fragment_container view with this fragment,
                // and add the transaction to the back stack
                transactionNDF.replace(R.id.nav_container, fragNDF, MainFragment.TAG);
                //transaction.addToBackStack(null);

                // Commit the transaction
                transactionNDF.commit();
                break;

            default:
                NavigationDrawerFragment NaDrawerFrag =
                        (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.frag_nav_drawer);
                NaDrawerFrag.setUp(
                        R.id.frag_nav_drawer,
                        findViewById(R.id.drawerLayout),
                        toolbar);
                break;
        }
    }



    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.home_menu, menu);

        mainMenu = menu;
        updateMessengerBadge();
        updateNotificationBadge(Notification.notificationsUnseen);

        return true;
    }

    private void updateMessengerBadge() {

        if (MessengerHelper.NbrMessagesManager.getNbrTotalMessages() > 0) {
            ActionItemBadge.update(this, mainMenu.findItem(R.id.messenger_action), CommunityMaterial.Icon.cmd_comment_multiple_outline,
                    ActionItemBadge.BadgeStyles.RED,
                    MessengerHelper.NbrMessagesManager.getNbrTotalMessages());
        } else {
            ActionItemBadge.hide(mainMenu.findItem(R.id.messenger_action));
        }
    }


    private void updateNotificationBadge(int notification) {

        Drawable bell_icon = new IconicsDrawable(this)
                .icon(CommunityMaterial.Icon.cmd_bell_outline)
                .color(ResourcesCompat.getColor(getResources(), R.color.color_toolbar_action, null))
                .sizeDp(18);

        if (notification > 0) {
            ActionItemBadge.update(this, mainMenu.findItem(R.id.notification_action), bell_icon,
                    ActionItemBadge.BadgeStyles.RED, notification);
        } else {

            ActionItemBadge.update(this, mainMenu.findItem(R.id.notification_action), bell_icon,
                    ActionItemBadge.BadgeStyles.GREY, Integer.MIN_VALUE);

        }

    }

    //Manage menu item
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {


        if (R.id.notification_action == item.getItemId()) {
            //start notification activity
            Intent intent = new Intent(this, NotificationActivity.class);
            startActivity(intent);
        } else if (R.id.messenger_action == item.getItemId()) {
            MainFragment.getPager().setCurrentItem(MainFragment.getPager().getChildCount() - 1);
        } else if (item.getItemId() == R.id.cart_icon) {
            Intent intent = new Intent(this, ProductCartActivity.class);
            startActivity(intent);
        }


        return super.onOptionsItemSelected(item);
    }


    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);

        // privacy & Condition of uses :
        // Checking for first time launch - before calling s
        (new Handler()).postDelayed(new Runnable() {
            @Override
            public void run() {
                session = new Session(getApplicationContext());
                if (session.isFirstTimeLaunch()) {
                    showPrivacyUsesConditionsDailog();
                }
            }
        }, 3000);


        opened = true;
    }

    @Override
    protected void onStop() {
        super.onStop();

        EventBus.getDefault().unregister(this);

    }

    @Subscribe
    public void onNewNotifs(BusMessage bus) {
        if (bus.getType() == BusMessage.GET_NBR_NEW_NOTIFS) {
            updateMessengerBadge();
        }
    }


    // This method will be called when a Notification is posted (in the UI thread for Toast)
    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
    public void onMessageEvent(NotifyDataNotificationEvent event) {
        if (event.message != null && event.message.equals("update_badges")) {
            updateNotificationBadge(Notification.notificationsUnseen);
            event.message = null;
        } else if (event.message != null && event.message.equals("cart_badge_counter")) {
            BadgeNotificationUtils.updateCartItemsBadge(this);
            event.message = null;
        }
    }


    @Subscribe
    public void onPageChangedMainFragement(MainFragment.PageViewEvent event) {
        toolbarTitle.setText(event.title);
    }

    public void setupToolbar() {

        toolbar = findViewById(R.id.app_bar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(true);
        getSupportActionBar().setDisplayUseLogoEnabled(false);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        toolbarDescription.setVisibility(View.GONE);

    }

    @Override
    protected void onResume() {
        super.onResume();

        try {
            updateMessengerBadge();
        } catch (Exception e) {
        }
    }

    //Get all categories from server and save them in  the database
    private void loadCategoriesApiCall() {

        ApiRequest.newGetInstance(Constances.API.API_USER_GET_CATEGORY, new ApiRequestListeners() {
            @Override
            public void onSuccess(Parser parser) {
                final CategoryParser mCategoryParser = new CategoryParser(parser);
                int success = Integer.parseInt(mCategoryParser.getStringAttr(Tags.SUCCESS));
                if (success == 1) {
                    //database.deleteCats();
                    //update list categories
                    CategoryController.removeAll();
                    CategoryController.insertCategories(
                            mCategoryParser.getCategories()
                    );
                }
            }

            @Override
            public void onFail(Map<String, String> errors) {

            }
        });

    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        Bundle extras = intent.getExtras();
        String event;
        if (extras != null) {
            event = extras.getString("Notified");
            if (APP_DEBUG) {
                Log.e("Notified", "Event notified  " + event);
            }
        } else {
            if (APP_DEBUG) {
                Log.e("Notified", "Extras are NULL");
            }

        }
    }


    @Override
    public void onBackPressed() {

        NavigationDrawerFragment.getInstance().closeDrawers();

        if (AppConfig.RATE_US_FORCE) {
            if (SettingsController.rateOnApp(this)) {
                super.onBackPressed();
            }
        } else {
            super.onBackPressed();
        }

    }


    private void showPrivacyUsesConditionsDailog() {
        final Dialog dialog = new Dialog(this);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // before
        dialog.setContentView(R.layout.dialog_privacy_conditions);
        dialog.setCancelable(false);
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        lp.copyFrom(dialog.getWindow().getAttributes());
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;


        String privacyMessageNonFormated = getResources().getString(R.string.msg_dialog_privacy_policy);
        ((TextView) dialog.findViewById(R.id.tv_content)).setText(Html.fromHtml(String.format(privacyMessageNonFormated, "<a href='" + getResources().getString(R.string.TERMS_OF_USE_URL) + "'>Terms-Conditions</a>", "<a href='" + getResources().getString(R.string.PRIVACY_POLICY_URL) + "'>Privacy-Policy</a>")));

        ((TextView) dialog.findViewById(R.id.tv_content)).setMovementMethod(LinkMovementMethod.getInstance());


        dialog.findViewById(R.id.bt_accept).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //disable privacy after the first time launch s
                session.setFirstTimeLaunch(false);

                //close the dialog
                dialog.dismiss();
            }
        });

        dialog.findViewById(R.id.bt_decline).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //close the app
                finish();
                System.exit(0);
            }
        });

        dialog.show();
        dialog.getWindow().setAttributes(lp);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == SearchDialog.AUTOCOMPLETE_REQUEST_CODE) {
            if (resultCode == AutocompleteActivity.RESULT_OK) {
                Place place = Autocomplete.getPlaceFromIntent(data);
                Log.i("CustomSearchFrag", "Place: " + place.getName() + ", " + place.getId() + ", " + place.getAddress() + ", " + place.getLatLng());
                EventBus.getDefault().postSticky(new LocationChangedEvent(place));

            } else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
                // TODO: Handle the showError.
                Status status = Autocomplete.getStatusFromIntent(data);
                Log.i("CustomSearchFrag", status.getStatusMessage());
            } else if (resultCode == AutocompleteActivity.RESULT_CANCELED) {
                // The user canceled the operation.
            }
        }
    }

    @Override
    public void onScrollHorizontal(int pos) {
        if (pos == 0) {
            hide_default_toolbar();
        } else {
            show_default_toolbar();
        }
    }

    @Override
    public void onScrollVertical(int scrollXs, int scrollY) {
        if (scrollY > 400)
            show_default_toolbar();
        else
            hide_default_toolbar();
    }


    private void show_default_toolbar() {
        toolbar.setVisibility(View.VISIBLE);
    }

    /*
     * Show home header
     */

    private void hide_default_toolbar() {
        toolbar.setVisibility(View.GONE);
    }


    private void requestNotificationPermission(){

        if (ContextCompat.checkSelfPermission(
                this, Manifest.permission.POST_NOTIFICATIONS) ==
                PackageManager.PERMISSION_GRANTED) {
            // You can use the API that requires the permission.

        } else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.POST_NOTIFICATIONS)) {
            NSLog.e(this.getClass().getName(),"Camera Permission is required");
        } else{
            // You can directly ask for the permission.
            // The registered ActivityResultCallback gets the result of this request.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                requestPermissionLauncher.launch(
                        Manifest.permission.POST_NOTIFICATIONS);
            }
        }
    }

    private ActivityResultLauncher<String> requestPermissionLauncher =
            registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                if (isGranted) {
                    //do something
                } else {
                    NSLog.e(this.getClass().getName(),"Camera Permission is required");
                }
            });

}
