package app.fedilab.fedilabtube;
/* Copyright 2020 Thomas Schneider
 *
 * This file is a part of TubeLab
 *
 * 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.
 *
 * TubeLab 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 TubeLab; if not,
 * see <http://www.gnu.org/licenses>. */

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.kobakei.ratethisapp.RateThisApp;

import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.AccountData.Account;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.OauthParams;
import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
import app.fedilab.fedilabtube.client.entities.Token;
import app.fedilab.fedilabtube.client.entities.UserMe;
import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo;
import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.services.RetrieveInfoService;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty;

import static app.fedilab.fedilabtube.helper.Helper.academies;

public class MainActivity extends AppCompatActivity {

    public static PeertubeInformation peertubeInformation;

    public static int PICK_INSTANCE = 5641;
    final FragmentManager fm = getSupportFragmentManager();
    Fragment active;
    private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
    private DisplayOverviewFragment overviewFragment;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = item -> {
        DisplayVideosFragment displayVideosFragment = null;
        switch (item.getItemId()) {
            case R.id.navigation_subscription:
                displayVideosFragment = subscriptionFragment;
                setTitle(R.string.subscriptions);
                break;
            case R.id.navigation_trending:
                setTitle(R.string.title_trending);
                displayVideosFragment = trendingFragment;
                break;
            case R.id.navigation_most_liked:
                setTitle(R.string.title_most_liked);
                displayVideosFragment = mostLikedFragment;
                break;
            case R.id.navigation_recently_added:
                setTitle(R.string.title_recently_added);
                displayVideosFragment = recentFragment;
                break;
            case R.id.navigation_local:
                setTitle(R.string.title_local);
                displayVideosFragment = locaFragment;
                break;
            case R.id.navigation_discover:
                setTitle(R.string.title_discover);
                fm.beginTransaction().hide(active).show(overviewFragment).commit();
                active = overviewFragment;
                return true;
        }
        if (displayVideosFragment != null) {
            fm.beginTransaction().hide(active).show(displayVideosFragment).commit();
            active = displayVideosFragment;
            return true;
        } else {
            return false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        BottomNavigationView navView = findViewById(R.id.nav_view);

        navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

        Fragment fragment = getSupportFragmentManager().findFragmentByTag("5");
        if(fragment != null)
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        fragment = getSupportFragmentManager().findFragmentByTag("4");
        if(fragment != null)
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        fragment = getSupportFragmentManager().findFragmentByTag("3");
        if(fragment != null)
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        fragment = getSupportFragmentManager().findFragmentByTag("2");
        if(fragment != null)
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        fragment = getSupportFragmentManager().findFragmentByTag("1");
        if(fragment != null)
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();

        recentFragment = new DisplayVideosFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.RECENT);
        recentFragment.setArguments(bundle);

        locaFragment = new DisplayVideosFragment();
        bundle = new Bundle();
        bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.LOCAL);
        locaFragment.setArguments(bundle);

        trendingFragment = new DisplayVideosFragment();
        bundle = new Bundle();
        bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.TRENDING);
        trendingFragment.setArguments(bundle);

        subscriptionFragment = new DisplayVideosFragment();
        bundle = new Bundle();
        bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.SUBSCRIBTIONS);
        subscriptionFragment.setArguments(bundle);

        mostLikedFragment = new DisplayVideosFragment();
        bundle = new Bundle();
        bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.MOST_LIKED);
        mostLikedFragment.setArguments(bundle);

        overviewFragment = new DisplayOverviewFragment();

        if( active == null) {
            active = overviewFragment;
        }
        fm.beginTransaction().add(R.id.nav_host_fragment, locaFragment, "5").hide(locaFragment).commit();

        if (!Helper.isLoggedIn(MainActivity.this)) {
            fm.beginTransaction().add(R.id.nav_host_fragment, recentFragment, "4").hide(recentFragment).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment, mostLikedFragment, "3").hide(mostLikedFragment).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment, trendingFragment, "2").hide(trendingFragment).commit();
            fm.beginTransaction().add(R.id.nav_host_fragment, overviewFragment, "1").commit();
        }
        toolbar.setOnClickListener(v->{
            if(active instanceof DisplayVideosFragment) {
                ((DisplayVideosFragment) active).scrollToTop();
            }else if(active instanceof DisplayOverviewFragment) {
                ((DisplayOverviewFragment) active).scrollToTop();
            }
        });

        setTitle(R.string.title_discover);

        if (Helper.isLoggedIn(MainActivity.this)) {
            navView.inflateMenu(R.menu.bottom_nav_menu_connected);
            final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
            String tokenStr = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
            String instance = Helper.getLiveInstance(MainActivity.this);
            SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();

            Account account = new AccountDAO(MainActivity.this, db).getAccountByToken(tokenStr);
            if (account != null) {
                OauthParams oauthParams = new OauthParams();
                oauthParams.setGrant_type("refresh_token");
                oauthParams.setClient_id(account.getClient_id());
                oauthParams.setClient_secret(account.getClient_secret());
                oauthParams.setRefresh_token(account.getRefresh_token());
                oauthParams.setAccess_token(account.getToken());
                new Thread(() -> {
                    try {
                        Token token = new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams);
                        if (token == null) {
                            runOnUiThread(() -> Helper.logoutCurrentUser(MainActivity.this, account));
                            return;
                        }
                        runOnUiThread(() -> {
                            //To avoid a token issue with subscriptions, adding fragment is done when the token is refreshed.
                            fm.beginTransaction().add(R.id.nav_host_fragment, recentFragment, "4").hide(recentFragment).commit();
                            fm.beginTransaction().add(R.id.nav_host_fragment, trendingFragment, "3").hide(trendingFragment).commit();
                            fm.beginTransaction().add(R.id.nav_host_fragment, subscriptionFragment, "2").hide(subscriptionFragment).commit();
                            fm.beginTransaction().add(R.id.nav_host_fragment, overviewFragment, "1").commit();
                        });

                        UserMe userMe = new RetrofitPeertubeAPI(MainActivity.this, instance, token.getAccess_token()).verifyCredentials();
                        if (userMe != null && userMe.getAccount() != null) {
                            new AccountDAO(MainActivity.this, db).updateAccount(userMe.getAccount());
                            SharedPreferences.Editor editor = sharedpreferences.edit();
                            editor.putString(Helper.PREF_KEY_ID, account.getId());
                            editor.putString(Helper.PREF_KEY_NAME, account.getUsername());
                            //Sync languages from server
                            List<String> videoLanguageServer = userMe.getVideoLanguages();
                            Set<String> videoLanguageServerSet = new TreeSet<>(videoLanguageServer);
                            videoLanguageServerSet.addAll(videoLanguageServer);
                            Set<String> videoLanguageLocal = sharedpreferences.getStringSet(getString(R.string.set_video_language_choice), null);
                            if (videoLanguageServerSet.size() > 0 && videoLanguageLocal != null) {
                                videoLanguageServer.addAll(videoLanguageLocal);
                            }
                            editor.putStringSet(getString(R.string.set_video_language_choice), videoLanguageServerSet);
                            editor.apply();
                        }
                    } catch (Error error) {
                        error.printStackTrace();
                    }
                }).start();
            }

        } else {
            navView.inflateMenu(R.menu.bottom_nav_menu);
        }
        startInForeground();

        if(BuildConfig.google_restriction && BuildConfig.full_instances) {
            RateThisApp.onCreate(this);
            RateThisApp.showRateDialogIfNeeded(this);
        }

    }

    private void startInForeground() {
        Intent notificationIntent = new Intent(this, RetrieveInfoService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(notificationIntent);
        } else {
            startService(notificationIntent);
        }
    }

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

        MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) myActionMenuItem.getActionView();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                Intent intent = new Intent(MainActivity.this, SearchActivity.class);
                Bundle b = new Bundle();
                String search = query.trim();
                b.putString("search", search);
                intent.putExtras(b);
                startActivity(intent);
                if (!searchView.isIconified()) {
                    searchView.setIconified(true);
                }
                myActionMenuItem.collapseActionView();
                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                return false;
            }
        });
        MenuItem instanceItem = menu.findItem(R.id.action_change_instance);
        MenuItem uploadItem = menu.findItem(R.id.action_upload);
        MenuItem myVideosItem = menu.findItem(R.id.action_myvideos);
        MenuItem playslistItem = menu.findItem(R.id.action_playlist);
        MenuItem historyItem = menu.findItem(R.id.action_history);
        MenuItem mostLikedItem = menu.findItem(R.id.action_most_liked);
        MenuItem settingsItem = menu.findItem(R.id.action_settings);
        MenuItem sepiaSearchItem = menu.findItem(R.id.action_sepia_search);
        if (Helper.isLoggedIn(MainActivity.this)) {
            instanceItem.setVisible(false);
            uploadItem.setVisible(true);
            myVideosItem.setVisible(true);
            playslistItem.setVisible(true);
            historyItem.setVisible(true);
            settingsItem.setVisible(false);
            mostLikedItem.setVisible(true);
        } else {
            instanceItem.setVisible(true);
            uploadItem.setVisible(false);
            myVideosItem.setVisible(false);
            playslistItem.setVisible(false);
            historyItem.setVisible(false);
            settingsItem.setVisible(true);
            mostLikedItem.setVisible(false);
        }
        if( !BuildConfig.full_instances) {
            sepiaSearchItem.setVisible(false);
        }
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_change_instance) {
            if (BuildConfig.full_instances) {
                showRadioButtonDialogFullInstances();
            } else {
                showRadioButtonDialog();
            }
            return true;
        } else if (item.getItemId() == R.id.action_settings) {
            Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
            startActivity(intent);
        } else if (item.getItemId() == R.id.action_account) {
            Intent intent;
            if (Helper.isLoggedIn(MainActivity.this)) {
                intent = new Intent(MainActivity.this, AccountActivity.class);
            } else {
                intent = new Intent(MainActivity.this, LoginActivity.class);
            }
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_upload) {
            Intent intent = new Intent(MainActivity.this, PeertubeUploadActivity.class);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_myvideos) {
            Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class);
            Bundle bundle = new Bundle();
            bundle.putSerializable("type", TimelineVM.TimelineType.MY_VIDEOS);
            intent.putExtras(bundle);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_history) {
            Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class);
            Bundle bundle = new Bundle();
            bundle.putSerializable("type", TimelineVM.TimelineType.HISTORY);
            intent.putExtras(bundle);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_most_liked) {
            Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class);
            Bundle bundle = new Bundle();
            bundle.putSerializable("type", TimelineVM.TimelineType.MOST_LIKED);
            intent.putExtras(bundle);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_playlist) {
            Intent intent = new Intent(MainActivity.this, AllPlaylistsActivity.class);
            startActivity(intent);
            return true;
        }else if(item.getItemId() == R.id.action_sepia_search) {
            Intent intent = new Intent(MainActivity.this, SepiaSearchActivity.class);
            startActivity(intent);
            return true;
        }else if (item.getItemId() == R.id.action_about) {
            Intent intent = new Intent(MainActivity.this, AboutActivity.class);
            startActivity(intent);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void setActive(DisplayVideosFragment displayVideosFragment){
        this.active = displayVideosFragment;
    }

    public void setSubscriptionFragment(DisplayVideosFragment displayVideosFragment) {
        this.subscriptionFragment = displayVideosFragment;
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent == null)
            return;
        Bundle extras = intent.getExtras();
        if (extras != null && extras.containsKey(Helper.INTENT_ACTION)) {
            if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) {
                recreate();
            }
        }
    }

    @SuppressLint("ApplySharedPref")
    private void showRadioButtonDialog() {

        AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
        alt_bld.setTitle(R.string.instance_choice);
        final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
        String acad = Helper.getLiveInstance(MainActivity.this);
        int i = 0;
        for (String item : academies) {
            if (Helper.getPeertubeUrl(item).compareTo(acad) == 0) {
                break;
            }
            i++;
        }
        alt_bld.setSingleChoiceItems(academies, i, (dialog, item) -> {
            String newInstance = academies[item];
            SharedPreferences.Editor editor = sharedpreferences.edit();
            editor.putString(Helper.PREF_INSTANCE, newInstance);
            editor.commit();
            dialog.dismiss();
            recreate();
        });
        alt_bld.setPositiveButton(R.string.close, (dialog, id) -> dialog.dismiss());
        AlertDialog alert = alt_bld.create();
        alert.show();
    }

    @SuppressLint("ApplySharedPref")
    private void showRadioButtonDialogFullInstances() {
        final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
        AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
        alt_bld.setTitle(R.string.instance_choice);
        String instance = Helper.getLiveInstance(MainActivity.this);
        final EditText input = new EditText(MainActivity.this);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);
        input.setLayoutParams(lp);
        alt_bld.setView(input);
        input.setText(instance);
        alt_bld.setPositiveButton(R.string.validate,
                (dialog, which) -> new Thread(() -> {
                    try {
                        String newInstance = input.getText().toString().trim();
                        WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(MainActivity.this, newInstance, null).getNodeInfo();
                        if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("peertube") == 0) {
                            SharedPreferences.Editor editor = sharedpreferences.edit();
                            editor.putString(Helper.PREF_INSTANCE, newInstance);
                            editor.commit();
                            runOnUiThread(() -> {
                                dialog.dismiss();
                                recreate();
                            });
                        } else {
                            runOnUiThread(() -> Toasty.error(MainActivity.this, getString(R.string.not_valide_instance), Toast.LENGTH_LONG).show());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }).start());
        alt_bld.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
        alt_bld.setNeutralButton(R.string.help, (dialog, which) -> {
            Intent intent = new Intent(MainActivity.this, InstancePickerActivity.class);
            startActivityForResult(intent, PICK_INSTANCE);
        });
        AlertDialog alert = alt_bld.create();
        alert.show();
    }


    @SuppressLint("ApplySharedPref")
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_INSTANCE && resultCode == Activity.RESULT_OK) {
            if (data != null && data.getData() != null) {
                final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedpreferences.edit();
                editor.putString(Helper.PREF_INSTANCE, String.valueOf(data.getData()));
                editor.commit();
                recreate();
            }
        }
    }
}