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.navigation.NavController;
import androidx.navigation.NavGraph;
import androidx.navigation.NavInflater;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.google.android.material.bottomnavigation.BottomNavigationView;

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.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;

    @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);
        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;
                        }
                        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);
        }

        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration;
        //Bottom menu won't be the same if the user is authenticated
        //When the user is authenticated, the subscription entry will be added and the local one removed.
        if (Helper.isLoggedIn(MainActivity.this)) {
            appBarConfiguration = new AppBarConfiguration.Builder(
                    R.id.navigation_discover, R.id.navigation_subscription, R.id.navigation_trending, R.id.navigation_local, R.id.navigation_recently_added)
                    .build();
        } else {
            appBarConfiguration = new AppBarConfiguration.Builder(
                    R.id.navigation_discover, R.id.navigation_trending, R.id.navigation_most_liked, R.id.navigation_recently_added, R.id.navigation_home)
                    .build();
        }


        startInForeground();
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
        if (navHostFragment != null) {
            NavInflater inflater = navHostFragment.getNavController().getNavInflater();
            NavGraph graph;
            //the menu is inflated for authenticated or not authenticated account
            if (Helper.isLoggedIn(MainActivity.this)) {
                graph = inflater.inflate(R.navigation.mobile_navigation_connected);
            } else {
                graph = inflater.inflate(R.navigation.mobile_navigation);
            }
            navHostFragment.getNavController().setGraph(graph);
            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
            NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
            NavigationUI.setupWithNavController(navView, navController);
        }
    }


    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);
        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);
        }
        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, MyVideosActivity.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, MyVideosActivity.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, MyVideosActivity.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_about) {
            Intent intent = new Intent(MainActivity.this, AboutActivity.class);
            startActivity(intent);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @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();
            }
        }
    }
}