/*
    This file is part of the dandelion*.

    dandelion* 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.

    dandelion* 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 the dandelion*.

    If not, see <http://www.gnu.org/licenses/>.
 */
package com.github.dfa.diaspora_android.activity;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.customtabs.CustomTabsSession;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.DiasporaAspect;
import com.github.dfa.diaspora_android.data.DiasporaPodList;
import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
import com.github.dfa.diaspora_android.listener.DiasporaUserProfileChangedListener;
import com.github.dfa.diaspora_android.listener.IntellihideToolbarActivityListener;
import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver;
import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver;
import com.github.dfa.diaspora_android.ui.BadgeDrawable;
import com.github.dfa.diaspora_android.ui.PodSelectionDialog;
import com.github.dfa.diaspora_android.ui.SearchOrCustomTextDialogCreator;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper;
import com.github.dfa.diaspora_android.ui.theme.ThemedActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.ActivityUtils;
import com.github.dfa.diaspora_android.util.AndroidBug5497Workaround;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.web.BrowserFragment;
import com.github.dfa.diaspora_android.web.ContextMenuWebView;
import com.github.dfa.diaspora_android.web.ProxyHandler;
import com.github.dfa.diaspora_android.web.WebHelper;
import com.github.dfa.diaspora_android.web.custom_tab.CustomTabActivityHelper;

import net.gsantner.opoc.format.markdown.SimpleMarkdownParser;
import net.gsantner.opoc.util.AndroidSupportMeWrapper;

import java.io.IOException;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends ThemedActivity
        implements NavigationView.OnNavigationItemSelectedListener,
        DiasporaUserProfileChangedListener,
        CustomTabActivityHelper.ConnectionCallback,
        IntellihideToolbarActivityListener,
        PodSelectionDialog.PodSelectionDialogResultListener {


    public static final int REQUEST_CODE_ASK_PERMISSIONS = 123;
    public static final int REQUEST_CODE__ACCESS_EXTERNAL_STORAGE = 124;
    public static final int INPUT_FILE_REQUEST_CODE_NEW = 1;
    public static final int INPUT_FILE_REQUEST_CODE_OLD = 2;

    public static final String ACTION_OPEN_URL = "com.github.dfa.diaspora_android.MainActivity.open_url";
    public static final String ACTION_OPEN_EXTERNAL_URL = "com.github.dfa.diaspora_android.MainActivity.open_external_url";
    public static final String ACTION_CHANGE_ACCOUNT = "com.github.dfa.diaspora_android.MainActivity.change_account";
    public static final String ACTION_CLEAR_CACHE = "com.github.dfa.diaspora_android.MainActivity.clear_cache";
    public static final String ACTION_UPDATE_TITLE_FROM_URL = "com.github.dfa.diaspora_android.MainActivity.set_title";
    public static final String URL_MESSAGE = "URL_MESSAGE";
    public static final String EXTRA_URL = "com.github.dfa.diaspora_android.extra_url";
    public static final String CONTENT_HASHTAG = "content://com.github.dfa.diaspora_android.mainactivity/";

    private App app;
    private CustomTabActivityHelper customTabActivityHelper;
    private AppSettings _appSettings;
    private DiasporaUrlHelper urls;
    private DiasporaUserProfile diasporaUserProfile;
    private final Handler uiHandler = new Handler();
    private OpenExternalLinkReceiver brOpenExternalLink;
    private BroadcastReceiver brSetTitle;
    private Snackbar snackbarExitApp, snackbarNoInternet, snackbarLastVisitedTimestampInStream;
    private FragmentManager fm;
    private CustomTabsSession customTabsSession;

    /**
     * UI Bindings
     */
    @BindView(R.id.main__appbar)
    AppBarLayout appBarLayout;

    @BindView(R.id.main__topbar)
    Toolbar toolbarTop;

    @BindView(R.id.fragment_container)
    FrameLayout fragmentContainer;

    @BindView(R.id.main__navigaion_view)
    NavigationView navView;

    @BindView(R.id.main__navdrawer)
    DrawerLayout navDrawer;

    RelativeLayout navDrawerLayout;
    LinearLayout navProfilePictureArea;


    // NavHeader cannot be bound by Butterknife
    private TextView navheaderTitle;
    private TextView navheaderDescription;
    private ImageView navheaderImage;

    private String textToBeShared;


    /**
     * END  UI Bindings
     */

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppLog.v(this, "onCreate()");

        // Pre UI
        ContextUtils.get().setAppLanguage(AppSettings.get().getLanguage());
        if (AppSettings.get().isEditorStatusBarHidden()) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }


        // Bind UI
        setContentView(R.layout.main__activity);
        ButterKnife.bind(this);
        if (AppSettings.get().isEditorStatusBarHidden()) {
            AndroidBug5497Workaround.assistActivity(this);
        }

        app = (App) getApplication();
        _appSettings = app.getSettings();
        diasporaUserProfile = app.getDiasporaUserProfile();
        diasporaUserProfile.setCallbackHandler(uiHandler);
        diasporaUserProfile.setListener(this);
        urls = new DiasporaUrlHelper(_appSettings);
        customTabActivityHelper = new CustomTabActivityHelper();
        customTabActivityHelper.setConnectionCallback(this);
        ProxyHandler.getInstance().updateProxySettings(this);

        fm = getSupportFragmentManager();
        setupUI();

        brOpenExternalLink = new OpenExternalLinkReceiver(this);
        brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() {
            public void setTitle(String url, int resId) {
                ThemedFragment top = getTopFragment();
                if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) {
                    MainActivity.this.setTitle(resId);
                    showLastVisitedTimestampMessageIfNeeded(url);
                }
            }

            public void setTitle(String url, String title) {
                ThemedFragment top = getTopFragment();
                if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) {
                    MainActivity.this.setTitle(title);
                }
            }
        });

        if (!_appSettings.hasPod()) {
            AppLog.d(this, "We have no pod. Show PodSelectionFragment");
            updateNavigationViewEntryVisibilities();
            showFragment(getFragment(PodSelectionFragment.TAG));
        } else {
            AppLog.d(this, "Pod found. Handle intents.");
            //Handle intent
            Intent intent = getIntent();
            if (intent != null && intent.getAction() != null) {
                handleIntent(intent);
            } else {
                openDiasporaUrl(urls.getStreamUrl());
            }
        }

        // Show first start / update dialog
        try {
            if (_appSettings.isAppCurrentVersionFirstStart(true)) {
                SimpleMarkdownParser smp = SimpleMarkdownParser.get().setDefaultSmpFilter(SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW);
                String html = "";
                html += smp.parse(getString(R.string.copyright_license_text_official).replace("\n", "  \n"), "").getHtml();
                html += "<br/><br/><br/><big><big>" + getString(R.string.changelog) + "</big></big><br/>" + smp.parse(getResources().openRawResource(R.raw.changelog), "", SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, SimpleMarkdownParser.FILTER_CHANGELOG).getHtml();
                html += "<br/><br/><br/><big><big>" + getString(R.string.licenses) + "</big></big><br/>" + smp.parse(getResources().openRawResource(R.raw.licenses_3rd_party), "").getHtml();
                ActivityUtils _au = new ActivityUtils(this);
                _au.showDialogWithHtmlTextView(R.string.licenses, html);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Setup the user interface. Set up both toolbars and initialize the snackbars.
     * Initialize the navigation drawer and apply intellihide settings.
     */
    private void setupUI() {
        AppLog.i(this, "setupUI()");

        // Setup _toolbar
        setSupportActionBar(toolbarTop);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
        setTitle(R.string.app_name);

        //Setup snackbar
        snackbarExitApp = Snackbar
                .make(fragmentContainer, R.string.do_you_want_to_exit, Snackbar.LENGTH_LONG)
                .setAction(android.R.string.yes, new View.OnClickListener() {
                    public void onClick(View view) {
                        finish();
                        moveTaskToBack(true);
                    }
                });
        snackbarLastVisitedTimestampInStream =
                Snackbar.make(fragmentContainer,
                        R.string.jump_to_last_visited_page_in_stream__appspecific, Snackbar.LENGTH_LONG)
                        .setAction(android.R.string.yes, new View.OnClickListener() {
                            public void onClick(View view) {
                                openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream()));
                            }
                        });
        snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.sorry_need_to_be_connected_to_internet, Snackbar.LENGTH_LONG);

        // Load app settings
        setupNavigationSlider();
        AppLog.v(this, "UI successfully set up");
    }

    /**
     * Get an instance of the ThemedFragment with the tag fragmentTag.
     * If there was no instance so far, create a new one and add it to the FragmentManagers pool.
     * If there is no Fragment with the corresponding Tag, return the top fragment.
     *
     * @param fragmentTag tag
     * @return corresponding Fragment
     */
    protected ThemedFragment getFragment(String fragmentTag) {
        ThemedFragment fragment = (ThemedFragment) fm.findFragmentByTag(fragmentTag);
        if (fragment != null) {
            return fragment;
        } else {
            switch (fragmentTag) {
                case DiasporaStreamFragment.TAG:
                    DiasporaStreamFragment dsf = new DiasporaStreamFragment();
                    fm.beginTransaction().add(dsf, fragmentTag).commit();
                    return dsf;
                case BrowserFragment.TAG:
                    BrowserFragment bf = new BrowserFragment();
                    fm.beginTransaction().add(bf, fragmentTag).commit();
                    return bf;
                case PodSelectionFragment.TAG:
                    PodSelectionFragment psf = new PodSelectionFragment();
                    fm.beginTransaction().add(psf, fragmentTag).commit();
                    return psf;
                default:
                    AppLog.e(this, "Invalid Fragment Tag: " + fragmentTag
                            + "\nAdd Fragments Tag to getFragment()'s switch case.");
                    return getTopFragment();
            }
        }
    }

    /**
     * Show DiasporaStreamFragment if necessary and load URL url
     *
     * @param url URL to load in the DiasporaStreamFragment
     */
    public void openDiasporaUrl(final String url) {
        AppLog.v(this, "openDiasporaUrl()");
        if (url != null && url.startsWith("http://127.0.0.1")) {
            // This URL seems to be called somehow, but it doesn't make sense ;)
            toolbarTop.postDelayed(() -> {
                Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL);
                i.putExtra(EXTRA_URL, "https://github.com/gsantner/dandelion/blob/master/README.md");
                LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
            }, 1000);
            return;
        }
        if (_appSettings.getPod() != null && _appSettings.getPod().getPodUrl() != null && _appSettings.getPod().getPodUrl().getBaseUrl() != null
                && url.startsWith(_appSettings.getPod().getPodUrl().getBaseUrl()) && !url.startsWith("https://dia.so/")) {
            DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG);
            showFragment(streamFragment);
            showLastVisitedTimestampMessageIfNeeded(url);
            streamFragment.loadUrl(url);
        } else {
            toolbarTop.postDelayed(() -> {
                Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL);
                i.putExtra(EXTRA_URL, url);
                LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
            }, 1000);
        }
    }

    public void showLastVisitedTimestampMessageIfNeeded(String url) {
        if (url.equals(urls.getStreamUrl()) && diasporaUserProfile.hasLastVisitedTimestampInStream()) {
            snackbarLastVisitedTimestampInStream.show();
            diasporaUserProfile.resetLastVisitedPositionInStream();
        }
    }

    /**
     * Show the Fragment fragment in R.id.fragment_container. If the fragment was already visible, do nothing.
     *
     * @param fragment Fragment to show
     */
    protected void showFragment(ThemedFragment fragment) {
        if (PodSelectionFragment.TAG.equals(fragment.getTag())) {
            Fragment fragment1 = fm.findFragmentByTag(DiasporaStreamFragment.TAG);
            if (fragment1 != null) {
                new net.gsantner.opoc.util.ContextUtils(this).restartApp(MainActivity.class);
            }
        }

        AppLog.v(this, "showFragment()");
        ThemedFragment currentTop = (ThemedFragment) fm.findFragmentById(R.id.fragment_container);
        if (currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) {
            AppLog.v(this, "Fragment was not visible. Replace it.");
            fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit();
            invalidateOptionsMenu();
            setToolbarIntellihide(_appSettings.isIntellihideToolbars() && fragment.isAllowedIntellihide());
        } else {
            AppLog.v(this, "Fragment was already visible. Do nothing.");
        }
    }

    /**
     * Initialize the navigation slider
     */
    private void setupNavigationSlider() {
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, navDrawer, toolbarTop, R.string.open_navdrawer, R.string.close_navdrawer);
        navDrawer.addDrawerListener(toggle);
        toggle.syncState();

        //NavigationView navView = ButterKnife.findById(this, R.id.nav_view);
        navView.setNavigationItemSelectedListener(this);

        View navHeader = navView.getHeaderView(0);
        navProfilePictureArea = ButterKnife.findById(navHeader, R.id.nav_profile_picture);
        navDrawerLayout = ButterKnife.findById(navHeader, R.id.nav_drawer);
        //Handle clicks on profile picture
        navProfilePictureArea.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                navDrawer.closeDrawer(GravityCompat.START);
                if (!_appSettings.getProfileId().equals("")) {
                    openDiasporaUrl(urls.getProfileUrl());
                }
            }
        });
        navheaderTitle = ButterKnife.findById(navHeader, R.id.navheader_title);
        navheaderDescription = ButterKnife.findById(navHeader, R.id.podselection__podupti_notice);
        navheaderImage = ButterKnife.findById(navHeader, R.id.navheader_user_image);

        if (!_appSettings.getName().equals("")) {
            navheaderTitle.setText(_appSettings.getName());
        }
        if (_appSettings.getPod() != null) {
            navheaderDescription.setText(_appSettings.getPod().getName());
        }
        String avatarUrl = _appSettings.getAvatarUrl();
        if (!avatarUrl.equals("")) {
            //Display app launcher icon instead of default avatar asset
            //(Which would by the way not load because of missing pod domain prefix in the url)
            if (avatarUrl.startsWith("/assets/user/default")) {
                AppLog.v(this, "Avatar appears to be an asset. Display launcher icon instead (avatarUrl=" + avatarUrl + ")");
                navheaderImage.setImageResource(R.drawable.ic_launcher);
            } else {
                // Try to load image
                if (!app.getAvatarImageLoader().loadToImageView(navheaderImage)) {
                    // If not yet loaded, start download
                    AppLog.v(this, "Avatar not cached. Start download: " + avatarUrl);
                    app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl);
                }
            }
        }
        updateNavigationViewEntryVisibilities();
    }

    protected void updateNavigationViewEntryVisibilities() {
        Menu navMenu = navView.getMenu();

        // Initially show all items visible when logged in
        navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), true);

        // Hide by app settings
        navMenu.findItem(R.id.nav_exit).setVisible(_appSettings.isVisibleInNavExit());
        navMenu.findItem(R.id.nav_activities).setVisible(_appSettings.isVisibleInNavActivities());
        navMenu.findItem(R.id.nav_aspects).setVisible(_appSettings.isVisibleInNavAspects());
        navMenu.findItem(R.id.nav_contacts).setVisible(_appSettings.isVisibleInNavContacts());
        navMenu.findItem(R.id.nav_commented).setVisible(_appSettings.isVisibleInNavCommented());
        navMenu.findItem(R.id.nav_followed_tags).setVisible(_appSettings.isVisibleInNavFollowed_tags());
        navMenu.findItem(R.id.nav_about).setVisible(_appSettings.isVisibleInNavHelp_license());
        navMenu.findItem(R.id.nav_liked).setVisible(_appSettings.isVisibleInNavLiked());
        navMenu.findItem(R.id.nav_mentions).setVisible(_appSettings.isVisibleInNavMentions());
        navMenu.findItem(R.id.nav_profile).setVisible(_appSettings.isVisibleInNavProfile());
        navMenu.findItem(R.id.nav_public).setVisible(_appSettings.isVisibleInNavPublic_activities());
        navMenu.findItem(R.id.nav_stream).setVisible(true);
        navMenu.findItem(R.id.nav_statistics).setVisible(_appSettings.isVisibleInNavStatistics());
        navMenu.findItem(R.id.nav_reports).setVisible(_appSettings.isVisibleInNavReports());
        navMenu.findItem(R.id.nav_toggle_desktop_page).setVisible(_appSettings.isVisibleInNavToggleMobileDesktop());
        navMenu.findItem(R.id.nav_product_support).setVisible(_appSettings.isVisibleInNavGsantnerAccount());


        // Hide whole group (for logged in use) if no pod was selected
        if (!_appSettings.hasPod()) {
            navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), false);
        }
    }

    /**
     * Open Stream when clicked on top _toolbar AND preference stream shortcut is true
     *
     * @param view selected view
     */
    @OnClick(R.id.main__topbar)
    public void onToolBarClicked(View view) {
        AppLog.i(this, "onToolBarClicked()");
        if (_appSettings.isTopbarStreamShortcutEnabled() && _appSettings.hasPod()) {
            onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream));
        }
    }

    /**
     * Forward incoming intents to handleIntent()
     *
     * @param intent incoming
     */
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleIntent(intent);
    }

    /**
     * Handle intents and execute intent specific actions
     *
     * @param intent intent to get handled
     */
    private void handleIntent(Intent intent) {
        AppLog.i(this, "handleIntent()");
        if (intent == null) {
            AppLog.v(this, "Intent was null");
            return;
        }

        String action = intent.getAction();
        String type = intent.getType();
        String loadUrl = null;
        AppLog.v(this, "Action: " + action + " Type: " + type);
        if (Intent.ACTION_MAIN.equals(action)) {
            loadUrl = urls.getStreamUrl();
        } else if (ACTION_OPEN_URL.equals(action)) {
            loadUrl = intent.getStringExtra(URL_MESSAGE);
        } else if (Intent.ACTION_VIEW.equals(action) && intent.getDataString() != null) {
            Uri data = intent.getData();
            if (data != null && data.toString().startsWith(CONTENT_HASHTAG)) {
                handleHashtag(intent);
                return;
            } else {
                loadUrl = intent.getDataString();
                AppLog.v(this, "Intent has a delicious URL for us: " + loadUrl);
            }
        } else if (ACTION_CHANGE_ACCOUNT.equals(action)) {
            AppLog.v(this, "Reset pod data and  show PodSelectionFragment");
            _appSettings.setPod(null);
            runOnUiThread(new Runnable() {
                public void run() {
                    navheaderTitle.setText(R.string.app_name);
                    navheaderDescription.setText(R.string.app_subtitle);
                    navheaderImage.setImageResource(R.drawable.ic_launcher);
                    app.resetPodData(((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView());
                }
            });
            showFragment(getFragment(PodSelectionFragment.TAG));
        } else if (ACTION_CLEAR_CACHE.equals(action)) {
            AppLog.v(this, "Clear WebView cache");
            runOnUiThread(new Runnable() {
                public void run() {
                    ContextMenuWebView wv = ((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView();
                    if (wv != null) {
                        wv.clearCache(true);
                    }
                }
            });

        } else if (Intent.ACTION_SEND.equals(action) && type != null) {
            switch (type) {
                case "text/plain":
                    if (intent.hasExtra(Intent.EXTRA_SUBJECT)) {
                        handleSendSubject(intent);
                    } else {
                        handleSendText(intent);
                    }
                    break;
                case "image/*":
                    handleSendImage(intent); //TODO: Add intent filter to Manifest and implement method
                    break;
            }
        } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
            /* TODO: Implement and add filter to manifest */
            return;
        } else if ("sc_new_post".equals(action)) {
            openDiasporaUrl(urls.getNewPostUrl());
            return;
        } else if ("sc_activities".equals(action)) {
            openDiasporaUrl(urls.getActivityUrl());
            return;
        } else if ("sc_contacts".equals(action)) {
            onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_aspects));
            return;
        } else if ("sc_tags".equals(action)) {
            onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_followed_tags));
            return;
        }
        //Catch split screen recreation
        if (action != null && action.equals(Intent.ACTION_MAIN) && getTopFragment() != null) {
            return;
        }

        if (loadUrl != null) {
            navDrawer.closeDrawers();
            openDiasporaUrl(loadUrl);
        }
    }

    /**
     * Handle activity results
     *
     * @param requestCode reqCode
     * @param resultCode  resCode
     * @param data        data
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        AppLog.v(this, "onActivityResult(): " + requestCode);
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Return the fragment which is currently displayed in R.id.fragment_container
     *
     * @return top fragment or null if there is none displayed
     */
    private ThemedFragment getTopFragment() {
        return (ThemedFragment) fm.findFragmentById(R.id.fragment_container);
    }

    /**
     * Handle presses on the back button
     */
    @Override
    public void onBackPressed() {
        AppLog.v(this, "onBackPressed()");
        if (navDrawer.isDrawerOpen(navView)) {
            navDrawer.closeDrawer(navView);
            return;
        }
        ThemedFragment top = getTopFragment();
        if (top != null) {
            AppLog.v(this, "Top Fragment is not null");
            if (!top.onBackPressed()) {
                AppLog.v(this, "Top Fragment.onBackPressed was false");
                AppLog.v(this, "BackStackEntryCount: " + fm.getBackStackEntryCount());
                if (fm.getBackStackEntryCount() > 0) {
                    fm.popBackStack();
                } else {
                    snackbarExitApp.show();
                }
                return;
            } else {
                AppLog.v(this, "Top Fragment.onBackPressed was true");
                return;
            }
        }

        if (!snackbarExitApp.isShown()) {
            snackbarExitApp.show();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        customTabActivityHelper.bindCustomTabsService(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        customTabActivityHelper.unbindCustomTabsService(this);
    }

    @Override
    protected void onPause() {
        AppLog.v(this, "onPause()");
        AppLog.v(this, "Unregister BroadcastReceivers");
        LocalBroadcastManager.getInstance(this).unregisterReceiver(brSetTitle);
        LocalBroadcastManager.getInstance(this).unregisterReceiver(brOpenExternalLink);
        super.onPause();
    }

    @Override
    protected void onResume() {
        AppLog.v(this, "onResume()");
        super.onResume();
        //new AndroidSupportMeWrapper(this).mainOnResume();
        AppLog.v(this, "Register BroadcastReceivers");
        LocalBroadcastManager.getInstance(this).registerReceiver(brSetTitle, new IntentFilter(ACTION_UPDATE_TITLE_FROM_URL));
        LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL));
        invalidateOptionsMenu();
        _appSettings = getAppSettings();
        if (_appSettings.isRecreateMainActivity()) {
            recreate();
        }
        setToolbarIntellihide(_appSettings.isIntellihideToolbars());
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayShowTitleEnabled(AppSettings.get().isShowTitleInMainView());
        }
        updateNavigationViewEntryVisibilities();
    }

    /**
     * Clear and repopulate top and bottom _toolbar.
     * Also add menu items of the displayed fragment
     *
     * @param menu top _toolbar
     * @return boolean
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        AppLog.v(this, "onCreateOptionsMenu()");
        boolean cache;

        //Clear the menus
        menu.clear();

        ThemedFragment top = getTopFragment();
        if (top != null) {
            if (!top.getFragmentTag().equals(PodSelectionFragment.TAG)) {
                cache = _appSettings.isExtendedNotificationsActivated();
                getMenuInflater().inflate(R.menu.main__menu_top, menu);
                menu.findItem(R.id.action_notifications).setVisible(!cache);
                menu.findItem(R.id.action_notifications_extended).setVisible(cache);
            }
        }

        ContextUtils cu = ContextUtils.get();
        final boolean darkBg = cu.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor());
        cu.tintMenuItems(menu, true, ContextCompat.getColor(this, darkBg ? R.color.white : R.color.black));
        cu.setSubMenuIconsVisiblity(menu, true);

        return true;
    }

    /**
     * Set the notification and messages counter in the top _toolbar
     *
     * @param menu menu
     * @return boolean
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem item;
        updateNavigationViewEntryVisibilities();

        if ((item = menu.findItem(R.id.action_notifications)) != null) {
            LayerDrawable icon = (LayerDrawable) item.getIcon();
            BadgeDrawable.setBadgeCount(this, icon, diasporaUserProfile.getNotificationCount());
        }

        if ((item = menu.findItem(R.id.action_conversations)) != null) {
            LayerDrawable icon = (LayerDrawable) item.getIcon();
            BadgeDrawable.setBadgeCount(this, icon, diasporaUserProfile.getUnreadMessagesCount());
        }
        return super.onPrepareOptionsMenu(menu);
    }

    /**
     * Handle clicks on the optionsmenu
     *
     * @param item item
     * @return boolean
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        AppLog.i(this, "onOptionsItemSelected()");
        switch (item.getItemId()) {
            case R.id.action_notifications: {
                if (_appSettings.isExtendedNotificationsActivated()) {
                    return true;
                }
                //Otherwise we execute the action of action_notifications_all
            }
            case R.id.action_notifications_all: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getNotificationsUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }


            case R.id.action_notifications_also_commented: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getSuburlNotificationsAlsoCommentedUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_notifications_comment_on_post: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getSuburlNotificationsCommentOnPostUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_notifications_liked: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getSuburlNotificationsLikedUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_notifications_mentioned: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getSuburlNotificationsMentionedUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_notifications_reshared: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getSuburlNotificationsResharedUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_notifications_started_sharing: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getSuburlNotificationsStartedSharingUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_conversations: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getConversationsUrl());
                    return true;
                } else {
                    snackbarNoInternet.show();
                    return false;
                }
            }

            case R.id.action_compose: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getNewPostUrl());
                } else {
                    snackbarNoInternet.show();
                }
                return true;
            }

            case R.id.action_search: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

                    @SuppressLint("InflateParams") View layout = getLayoutInflater().inflate(R.layout.ui__dialog_search__people_tags, null, false);
                    final EditText input = layout.findViewById(R.id.dialog_search__input);
                    input.setMaxLines(1);
                    input.setSingleLine(true);
                    ThemeHelper.updateEditTextColor(input);
                    final DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int which) {
                            String query = input.getText().toString().trim().replaceAll((which == DialogInterface.BUTTON_NEGATIVE ? "\\*" : "\\#"), "");
                            if (query.equals("")) {
                                Snackbar.make(fragmentContainer, R.string.please_add_a_name, Snackbar.LENGTH_LONG).show();
                            } else {
                                openDiasporaUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query));
                            }
                            getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
                            imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
                        }
                    };

                    final AlertDialog dialog = new ThemedAlertDialogBuilder(this, _appSettings)
                            .setView(layout).setTitle(R.string.search_alert_title)
                            .setCancelable(true)
                            .setPositiveButton(R.string.by_tags, clickListener)
                            .setNegativeButton(R.string.by_people, clickListener)
                            .create();

                    input.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                            if (actionId == EditorInfo.IME_ACTION_DONE) {
                                dialog.hide();
                                clickListener.onClick(null, 0);
                                return true;
                            }
                            return false;
                        }
                    });

                    // Popup keyboard
                    dialog.show();
                    input.requestFocus();
                    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

                } else {
                    snackbarNoInternet.show();
                }
                return true;
            }
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onUserProfileNameChanged(DiasporaUserProfile diasporaUserProfile, String name) {
        AppLog.i(this, "onUserProfileNameChanged()");
        // Update the profile name in the navigation slider
        navheaderTitle.setText(name);
    }

    @Override
    public void onUserProfileAvatarChanged(DiasporaUserProfile diasporaUserProfile, String avatarUrl) {
        AppLog.i(this, "onUserProfileAvatarChanged()");
        // Update the profile picture in the navigation slider
        app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl);
    }

    /**
     * Handle hashtag clicks. Open the new-post-url and inject the clicked hashtag into the post-editor
     *
     * @param intent intent
     */
    private void handleHashtag(Intent intent) {
        AppLog.v(this, "handleHashtag()");
        try {
            setSharedTexts(null, intent.getData().toString().split("/")[3]);
        } catch (Exception e) {
            AppLog.e(this, e.toString());
        }
        openDiasporaUrl(urls.getNewPostUrl());
    }

    /**
     * Open the new-post-url and inject text that was shared into the app into the post editors text field
     *
     * @param intent shareTextIntent
     */
    private void handleSendText(Intent intent) {
        AppLog.v(this, "handleSendText()");
        try {
            setSharedTexts(null, intent.getStringExtra(Intent.EXTRA_TEXT));
            openDiasporaUrl(urls.getNewPostUrl());
        } catch (Exception e) {
            AppLog.e(this, e.toString());
        }
    }

    /**
     * Handle sent text + subject
     *
     * @param intent intent
     */
    private void handleSendSubject(Intent intent) {
        AppLog.v(this, "handleSendSubject()");
        try {
            setSharedTexts(intent.getStringExtra(Intent.EXTRA_SUBJECT), intent.getStringExtra(Intent.EXTRA_TEXT));
            openDiasporaUrl(urls.getNewPostUrl());
        } catch (Exception e) {
            AppLog.e(this, e.toString());
        }
    }

    /**
     * TODO: MOVE
     * Set sharedText variable to escaped and formatted subject + body.
     * If subject is null, only the body will be set. Else the subject will be set as header.
     * Depending on whether the user has the setting isAppendSharedViaApp set, a reference to
     * the app will be added at the bottom
     *
     * @param sharedSubject post subject or null
     * @param sharedBody    post text
     */
    private void setSharedTexts(String sharedSubject, String sharedBody) {
        AppLog.i(this, "setSharedTexts()");
        String body = WebHelper.replaceUrlWithMarkdown(sharedBody);
        if (_appSettings.isAppendSharedViaApp()) {
            AppLog.v(this, "Append app reference to shared text");
            body = body + "\n\n" + getString(R.string.shared_via_app);
        }
        final String escapedBody = WebHelper.escapeHtmlText(body);
        if (sharedSubject != null) {
            AppLog.v(this, "Append subject to shared text");
            String escapedSubject = WebHelper.escapeHtmlText(WebHelper.replaceUrlWithMarkdown(sharedSubject));
            AppLog.v(this, "Set shared text; Subject: \"" + escapedSubject + "\" Body: \"" + escapedBody + "\"");
            textToBeShared = "**" + escapedSubject + "** " + escapedBody;
        } else {
            AppLog.v(this, "Set shared text; Subject: \"null\" Body: \"" + sharedBody + "\"");
            textToBeShared = escapedBody;
        }
    }

    /**
     * Share an image shared to the app via diaspora
     *
     * @param intent shareImageIntent
     */
    //TODO: Implement some day
    private void handleSendImage(Intent intent) {
        AppLog.i(this, "handleSendImage()");
        final Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
        if (imageUri != null) {
            AppLog.v(this, "imageUri is not null. Handle shared image");
        } else {
            AppLog.w(this, "imageUri is null. Cannot precede.");
        }
        Toast.makeText(this, "Not yet implemented.", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onNotificationCountChanged(DiasporaUserProfile diasporaUserProfile, int notificationCount) {
        AppLog.i(this, "onNotificationCountChanged()");
        // Count saved in DiasporaUserProfile
        // Invalidate the top _toolbar to update the unread messages counter
        invalidateOptionsMenu();
    }


    @Override
    public void onUnreadMessageCountChanged(DiasporaUserProfile diasporaUserProfile, int unreadMessageCount) {
        AppLog.i(this, "onUnreadMessageCountChanged()");
        // Count saved in DiasporaUserProfile
        // Invalidate the top _toolbar to update the unread messages counter
        invalidateOptionsMenu();
    }

    @Override
    public void onCustomTabsConnected() {
        if (customTabsSession == null) {
            AppLog.i(this, "CustomTabs warmup: " + customTabActivityHelper.warmup(0));
            customTabsSession = customTabActivityHelper.getSession();
        }
    }

    @Override
    public void onPodSelectionDialogResult(DiasporaPodList.DiasporaPod pod, boolean accepted) {
        if (accepted) {
            invalidateOptionsMenu();
            navheaderDescription.setText(pod.getName());
        }
    }

    @Override
    public void onCustomTabsDisconnected() {

    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        AppLog.v(this, "onNavigationItemsSelected()");
        // Handle navigation view item clicks here.
        switch (item.getItemId()) {
            case R.id.nav_stream: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getStreamUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_profile: {
                if (!_appSettings.getProfileId().equals("")) {
                    openDiasporaUrl(urls.getProfileUrl());
                }
            }
            break;

            case R.id.nav_followed_tags: {
                SearchOrCustomTextDialogCreator.showDiasporaTagsDialog(this, arg -> {
                    if (arg.startsWith(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX)) {
                        arg = arg.replace(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX, "").trim();
                        if (arg.equals(getString(R.string.manage_hashtags))) {
                            openDiasporaUrl(urls.getManageTagsUrl());
                        } else {
                            openDiasporaUrl(urls.getAllFollowedTagsUrl());
                        }
                    } else {
                        openDiasporaUrl(urls.getSearchTagsUrl(arg));
                    }
                });
            }
            break;

            case R.id.nav_aspects: {
                SearchOrCustomTextDialogCreator.showDiasporaAspectsDialog(this, arg -> {
                    if (arg.startsWith(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX)) {
                        arg = arg.replace(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX, "").trim();
                        if (arg.equals(getString(R.string.manage_your_contact_list))) {
                            openDiasporaUrl(urls.getContactsUrl());
                        } else if (arg.equals(getString(R.string.nav_profile))) {
                            openDiasporaUrl(urls.getProfileUrl());
                        }
                    } else {
                        for (DiasporaAspect daspect : _appSettings.getAspects()) {
                            if (arg.equals(daspect.name)) {
                                openDiasporaUrl(urls.getAspectUrl(Long.toString(daspect.id)));
                                break;
                            }
                        }
                    }
                });
            }
            break;

            case R.id.nav_contacts: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getContactsUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_activities: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getActivityUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_liked: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getLikedPostsUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_commented: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getCommentedUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_mentions: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getMentionsUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_public: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getPublicUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_reports: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getReportsUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_statistics: {
                if (WebHelper.isOnline(MainActivity.this)) {
                    openDiasporaUrl(urls.getStatisticsUrl());
                } else {
                    snackbarNoInternet.show();
                }
            }
            break;

            case R.id.nav_toggle_desktop_page: {
                openDiasporaUrl(urls.getToggleMobileUrl());
            }
            break;

            case R.id.nav_product_support: {
                openDiasporaUrl(urls.getProfileUrl("d1cbdd70095301341e834860008dbc6c"));
            }
            break;

            case R.id.nav_exit: {
                moveTaskToBack(true);
                finish();
            }
            break;

            case R.id.nav_settings: {
                startActivity(new Intent(this, SettingsActivity.class));
            }
            break;

            case R.id.nav_about: {
                startActivity(new Intent(MainActivity.this, AboutActivity.class));
            }
            break;
        }

        navDrawer.closeDrawer(GravityCompat.START);
        return true;
    }

    /**
     * React to results of requestPermission
     *
     * @param requestCode  resCode
     * @param permissions  requested permissions
     * @param grantResults granted results
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE__ACCESS_EXTERNAL_STORAGE:
                if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    AppLog.i(this, "onRequestPermissionsResult: Permission to access external storage granted");
                    Toast.makeText(this, R.string.permission_granted_try_again, Toast.LENGTH_SHORT).show();
                } else {
                    AppLog.w(this, "onRequestPermissionsResult: Permission to access external storage denied");
                    Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show();
                }
                return;

            default:
                super.onRequestPermissionsResult(requestCode, permissions,
                        grantResults);
        }
    }

    /**
     * Return the string that will be shared into the new-post-editor
     *
     * @return String
     */
    public String getTextToBeShared() {
        return textToBeShared;
    }

    /**
     * Set the string that will be shared into the new-post-editor
     *
     * @param textToBeShared text that will be shared into the post-editor
     */
    public void setTextToBeShared(String textToBeShared) {
        this.textToBeShared = textToBeShared;
    }

    @Override
    protected void applyColorToViews() {
        ThemeHelper.updateToolbarColor(toolbarTop);
        navDrawerLayout.setBackgroundColor(_appSettings.getPrimaryColor());
        navProfilePictureArea.setBackgroundColor(_appSettings.getPrimaryColor());
        if (_appSettings.isAmoledColorMode()) {
            navView.setItemTextColor(ColorStateList.valueOf(Color.GRAY));
            navView.setItemIconTintList(ColorStateList.valueOf(Color.GRAY));
            navView.setBackgroundColor(Color.BLACK);
            navheaderTitle.setTextColor(Color.GRAY);
            navheaderDescription.setTextColor(Color.DKGRAY);
        }

        int popupTheme = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor())
                ? R.style.AppTheme_PopupOverlay_Dark : R.style.AppTheme_PopupOverlay_Light;
        toolbarTop.setPopupTheme(popupTheme);
    }

    public void setToolbarIntellihide(boolean enable) {
        AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams();
        if (enable) {
            AppLog.d(this, "Enable Intellihide");
            params.setScrollFlags(toolbarDefaultScrollFlags);

        } else {
            AppLog.d(this, "Disable Intellihide");
            params.setScrollFlags(0);  // clear all scroll flags
        }
        appBarLayout.setExpanded(true, true);
    }
}
