package com.shoutcast.stm.radio_nome.fragments;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.fragment.app.Fragment;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatSeekBar;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.cleveroad.audiovisualization.AudioVisualization;
import com.cleveroad.audiovisualization.DbmHandler;
import com.cleveroad.audiovisualization.VisualizerDbmHandler;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import com.shoutcast.stm.radio_nome.Config;
import com.shoutcast.stm.radio_nome.R;
import com.shoutcast.stm.radio_nome.activities.MainActivity;
import com.shoutcast.stm.radio_nome.models.ItemRadio;
import com.shoutcast.stm.radio_nome.services.PlaybackStatus;
import com.shoutcast.stm.radio_nome.services.RadioManager;
import com.shoutcast.stm.radio_nome.services.metadata.Metadata;
import com.shoutcast.stm.radio_nome.utilities.CollapseControllingFragment;
import com.shoutcast.stm.radio_nome.utilities.Constant;
import com.shoutcast.stm.radio_nome.utilities.PermissionsFragment;
import com.shoutcast.stm.radio_nome.utilities.Tools;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.List;

/**
 * This fragment is used to listen to a radio station
 */
public class FragmentRadioAdminPanel extends Fragment implements OnClickListener, PermissionsFragment, CollapseControllingFragment, Tools.EventListener {

    private RadioManager radioManager;
    private Activity activity;
    private ImageView albumArtView;
    private RelativeLayout relativeLayout;
    private ProgressBar progressBar;
    private FloatingActionButton buttonPlayPause;
    private Toolbar toolbar;
    private MainActivity mainActivity;
    private AudioVisualization audioVisualization;
    LinearLayout lyt_visualizer;
    AudioManager audioManager;
    AppCompatSeekBar appCompatSeekBar;
    ImageButton img_volume;
    LinearLayout lyt_volume_bar;
    private InterstitialAd interstitialAd;
    int counter = 1;
    private String radio_url, radio_name;
    TextView nowPlayingTitle, nowPlaying;

    public FragmentRadioAdminPanel() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mainActivity = (MainActivity) activity;
    }

    /**
     * Called when the activity is first created.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        relativeLayout = (RelativeLayout) inflater.inflate(R.layout.fragment_radio, container, false);

        lyt_volume_bar = (LinearLayout) relativeLayout.findViewById(R.id.lyt_volume_bar);
        toolbar = (Toolbar) relativeLayout.findViewById(R.id.toolbar);
        nowPlayingTitle = relativeLayout.findViewById(R.id.now_playing_title);
        nowPlaying = relativeLayout.findViewById(R.id.now_playing);

        setupToolbar();

        loadInterstitialAd();

        setHasOptionsMenu(true);

        initializeUIElements();

        if (Config.ENABLE_VOLUME_BAR) {
            lyt_volume_bar.setVisibility(View.VISIBLE);
            initVolumeBar();
        } else {
            lyt_volume_bar.setVisibility(View.GONE);
        }

        //Initialize visualizer or imageview for album art
        if (Config.ENABLE_ALBUM_ART) {
            albumArtView.setVisibility(View.VISIBLE);
        } else {
            albumArtView.setVisibility(View.GONE);
        }

        if (Config.ENABLE_VISUALIZER) {
            lyt_visualizer.setVisibility(View.VISIBLE);
        } else {
            lyt_visualizer.setVisibility(View.GONE);
        }

        albumArtView.setImageResource(Tools.BACKGROUND_IMAGE_ID);

        onBackPressed();

        return relativeLayout;
    }

    private void setupToolbar() {
        toolbar.setTitle(getString(R.string.app_name));
        mainActivity.setSupportActionBar(toolbar);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mainActivity.setupNavigationDrawer(toolbar);
        activity = getActivity();

        if (Tools.isNetworkActive(getActivity())) {
            new MyTask().execute(Config.ADMIN_PANEL_URL + "/api.php");
        } else {
            Toast.makeText(getActivity(), getResources().getString(R.string.dialog_internet_description), Toast.LENGTH_SHORT).show();
        }

        Tools.isOnlineShowDialog(activity);

        //Get the radioManager
        radioManager = RadioManager.with();

        progressBar.setVisibility(View.VISIBLE);

        //Obtain the actual radio url
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        progressBar.setVisibility(View.INVISIBLE);
                        updateButtons();
                    }
                });
            }
        });

        if (isPlaying()) {
            onAudioSessionId(RadioManager.getService().getAudioSessionId());
        }

    }

    @Override
    public void onEvent(String status) {

        switch (status) {
            case PlaybackStatus.LOADING:
                progressBar.setVisibility(View.VISIBLE);
                break;

            case PlaybackStatus.ERROR:
                makeSnackBar(R.string.error_retry);
                break;
        }

        if (!status.equals(PlaybackStatus.LOADING))
            progressBar.setVisibility(View.INVISIBLE);

        updateButtons();

    }

    @Override
    public void onAudioSessionId(Integer i) {
        if (Config.ENABLE_VISUALIZER) {
            VisualizerDbmHandler vizualizerHandler = DbmHandler.Factory.newVisualizerHandler(getContext(), i);
            audioVisualization.linkTo(vizualizerHandler);
            audioVisualization.onResume();
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Tools.registerAsListener(this);
    }

    @Override
    public void onStop() {
        Tools.unregisterAsListener(this);
        super.onStop();
    }

    @Override
    public void onDestroy() {
        if (!radioManager.isPlaying())
            radioManager.unbind(getContext());

        audioVisualization.release();
        super.onDestroy();
    }

    @Override
    public void onPause() {
        super.onPause();

        audioVisualization.onPause();
    }

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

        updateButtons();
        radioManager.bind(getContext());

        if (audioVisualization != null)
            audioVisualization.onResume();
    }

    private class MyTask extends AsyncTask<String, Void, String> {

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

            buttonPlayPause.setVisibility(View.INVISIBLE);
            nowPlaying.setText(R.string.loading_progress);
        }

        @Override
        protected String doInBackground(String... params) {
            return Tools.getJSONString(params[0]);
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            buttonPlayPause.setVisibility(View.VISIBLE);

            if (null == result || result.length() == 0) {
                Toast.makeText(getActivity(), getResources().getString(R.string.dialog_internet_description), Toast.LENGTH_SHORT).show();

            } else {

                try {
                    JSONObject mainJson = new JSONObject(result);
                    JSONArray jsonArray = mainJson.getJSONArray("result");
                    JSONObject c = null;
                    for (int i = 0; i < jsonArray.length(); i++) {
                        c = jsonArray.getJSONObject(i);

                        radio_name = c.getString("radio_name");
                        radio_url = c.getString("radio_url");

                        Constant.itemRadio = new ItemRadio(radio_name, radio_url);

                    }

                    nowPlayingTitle.setText(R.string.now_playing);
                    nowPlaying.setText(radio_name);

                    if (Config.ENABLE_AUTO_PLAY) {
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                buttonPlayPause.performClick();
                            }
                        }, 1000);
                    } else {
                        Log.d("INFO", "Auto play is disabled");
                    }

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void initializeUIElements() {
        progressBar = relativeLayout.findViewById(R.id.progressBar);
        progressBar.setMax(100);
        progressBar.setVisibility(View.VISIBLE);

        albumArtView = relativeLayout.findViewById(R.id.albumArt);
        audioVisualization = relativeLayout.findViewById(R.id.visualizer_view);
        lyt_visualizer = relativeLayout.findViewById(R.id.lyt_visualizer);

        buttonPlayPause = relativeLayout.findViewById(R.id.btn_play_pause);
        buttonPlayPause.setOnClickListener(this);

        updateButtons();
    }

    public void updateButtons() {
        if (isPlaying() || progressBar.getVisibility() == View.VISIBLE) {
            //If another stream is playing, show this in the layout
            if (RadioManager.getService() != null && radio_url != null && !radio_url.equals(RadioManager.getService().getStreamUrl())) {
                buttonPlayPause.setImageResource(R.drawable.ic_play_white);
                relativeLayout.findViewById(R.id.already_playing_tooltip).setVisibility(View.VISIBLE);
                //If this stream is playing, adjust the buttons accordingly
            } else {
                buttonPlayPause.setImageResource(R.drawable.ic_pause_white);
                relativeLayout.findViewById(R.id.already_playing_tooltip).setVisibility(View.GONE);
            }
        } else {
            //If this stream is paused, adjust the buttons accordingly
            buttonPlayPause.setImageResource(R.drawable.ic_play_white);
            relativeLayout.findViewById(R.id.already_playing_tooltip).setVisibility(View.GONE);

            updateMediaInfoFromBackground(null, null);
        }
    }

    @Override
    public void onClick(View v) {
        requestStoragePermission();
    }

    private void startStopPlaying() {
        //Start the radio playing
        radioManager.playOrPause(radio_url);
        //Update the UI
        updateButtons();
    }

    private void stopService() {
        radioManager.stopServices();
        Tools.unregisterAsListener(this);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_main, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.share:
                Intent sendInt = new Intent(Intent.ACTION_SEND);
                sendInt.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
                sendInt.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_text) + "\nhttps://play.google.com/store/apps/details?id=" + getActivity().getPackageName());
                sendInt.setType("text/plain");
                startActivity(Intent.createChooser(sendInt, "Share"));
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    //@param info - the text to be updated. Giving a null string will hide the info.
    public void updateMediaInfoFromBackground(String info, Bitmap image) {

        if (info != null)
            nowPlaying.setText(info);

        if (info != null && nowPlayingTitle.getVisibility() == View.GONE) {
            nowPlayingTitle.setVisibility(View.VISIBLE);
            nowPlaying.setVisibility(View.VISIBLE);
        } else if (info == null) {
            nowPlayingTitle.setVisibility(View.VISIBLE);
            nowPlayingTitle.setText(R.string.now_playing);
            nowPlaying.setVisibility(View.VISIBLE);
            nowPlaying.setText(radio_name);
        }

        if (image != null) {
            albumArtView.setImageBitmap(image);
        } else {
            albumArtView.setImageResource(Tools.BACKGROUND_IMAGE_ID);
        }

    }

    @Override
    public String[] requiredPermissions() {
        if (Config.ENABLE_VISUALIZER)
            return new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_PHONE_STATE};
        else
            return new String[]{Manifest.permission.READ_PHONE_STATE};
    }

    @Override
    public void onMetaDataReceived(Metadata meta, Bitmap image) {
        //Update the mediainfo shown above the controls
        String artistAndSong = null;
        if (meta != null && meta.getArtist() != null)
            artistAndSong = meta.getArtist() + " - " + meta.getSong();
        updateMediaInfoFromBackground(artistAndSong, image);
    }

    private boolean isPlaying() {
        return (null != radioManager && null != RadioManager.getService() && RadioManager.getService().isPlaying());
    }

    @Override
    public boolean supportsCollapse() {
        return false;
    }

    private void makeSnackBar(int text) {
        Snackbar bar = Snackbar.make(buttonPlayPause, text, Snackbar.LENGTH_SHORT);
        bar.show();
        ((TextView) bar.getView().findViewById(com.google.android.material.R.id.snackbar_text)).setTextColor(getResources().getColor(R.color.white));
    }

    public void onBackPressed() {
        ((MainActivity) getActivity()).setOnBackClickListener(new MainActivity.OnBackClickListener() {
            @Override
            public boolean onBackClick() {
                exitDialog();
                return true;
            }
        });
    }

    public void exitDialog() {
        AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
        dialog.setIcon(R.mipmap.ic_launcher);
        dialog.setTitle(R.string.app_name);
        dialog.setMessage(getResources().getString(R.string.message));
        dialog.setPositiveButton(getResources().getString(R.string.quit), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                stopService();
                getActivity().finish();
            }
        });

        dialog.setNegativeButton(getResources().getString(R.string.minimize), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                minimizeApp();
            }
        });

        dialog.setNeutralButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

            }
        });
        dialog.show();
    }

    public void minimizeApp() {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    private void requestStoragePermission() {
        Dexter.withActivity(getActivity())
                .withPermissions(
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.MODIFY_AUDIO_SETTINGS,
                        Manifest.permission.READ_PHONE_STATE)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            if (!isPlaying()) {
                                if (radio_url != null) {

                                    startStopPlaying();
                                    showInterstitialAd();

                                    //Check the sound level
                                    AudioManager audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
                                    int volume_level = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
                                    if (volume_level < 2) {
                                        makeSnackBar(R.string.volume_low);
                                    }

                                } else {
                                    //The loading of urlToPlay should happen almost instantly, so this code should never be reached
                                    makeSnackBar(R.string.error_retry_later);
                                }
                            } else {
                                startStopPlaying();
                            }
                        }
                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // show alert dialog navigating to Settings
                            showSettingsDialog();
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                }).
                withErrorListener(new PermissionRequestErrorListener() {
                    @Override
                    public void onError(DexterError error) {
                        Toast.makeText(getActivity(), "Error occurred! " + error.toString(), Toast.LENGTH_SHORT).show();
                    }
                })
                .onSameThread()
                .check();
    }

    private void showSettingsDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Need Permissions");
        builder.setMessage("This app needs permission to use this feature. You can grant them in app settings.");
        builder.setPositiveButton("GOTO SETTINGS", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
                openSettings();
            }
        });
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        builder.show();
    }

    private void openSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, 101);
    }

    public void initVolumeBar() {
        appCompatSeekBar = (AppCompatSeekBar) relativeLayout.findViewById(R.id.volumeBar);

        audioManager = (AudioManager) mainActivity.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, Config.DEFAULT_VOLUME, 0);

        appCompatSeekBar.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
        appCompatSeekBar.setProgress(Config.DEFAULT_VOLUME);
        appCompatSeekBar.setMax(15);

        img_volume = (ImageButton) relativeLayout.findViewById(R.id.ic_volume);
        img_volume.setImageResource(R.drawable.ic_volume);

        appCompatSeekBar.setOnSeekBarChangeListener(new AppCompatSeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);

                if (progress == 0) {
                    Toast.makeText(getActivity(), "Volume OFF", Toast.LENGTH_SHORT).show();
                    img_volume.setImageResource(R.drawable.ic_volume_off);
                } else if (progress == 15) {
                    Toast.makeText(getActivity(), "Volume Max", Toast.LENGTH_SHORT).show();
                    img_volume.setImageResource(R.drawable.ic_volume);
                } else {
                    img_volume.setImageResource(R.drawable.ic_volume);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    private void loadInterstitialAd() {
        if (Config.ENABLE_ADMOB_INTERSTITIAL_ON_PLAY) {
            interstitialAd = new InterstitialAd(getActivity());
            interstitialAd.setAdUnitId(getResources().getString(R.string.admob_interstitial_unit_id));
            interstitialAd.loadAd(new AdRequest.Builder().build());
            interstitialAd.setAdListener(new AdListener() {
                @Override
                public void onAdClosed() {
                    interstitialAd.loadAd(new AdRequest.Builder().build());
                }
            });
        } else {
            Log.d("INFO", "AdMob Interstitial is Disabled");
        }
    }

    private void showInterstitialAd() {
        if (Config.ENABLE_ADMOB_INTERSTITIAL_ON_PLAY) {
            if (interstitialAd != null && interstitialAd.isLoaded()) {
                if (counter == Config.ADMOB_INTERSTITIAL_ON_PLAY_INTERVAL) {
                    interstitialAd.show();
                    counter = 1;
                } else {
                    counter++;
                }
            } else {
                Log.d("INFO", "Interstitial Ad is Disabled");
            }
        } else {
            Log.d("INFO", "AdMob Interstitial is Disabled");
        }
    }

}