package com.kpstv.youtube;

import android.Manifest;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette;
import android.text.Spanned;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.TransitionOptions;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.coremedia.iso.boxes.Container;
import com.downloader.Error;
import com.downloader.OnDownloadListener;
import com.downloader.PRDownloader;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.googlecode.mp4parser.authoring.Movie;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
import com.kpstv.youtube.adapters.DownloadAdpater2;
import com.kpstv.youtube.adapters.PlayerAdapter;
import com.kpstv.youtube.fragments.DownloadBottomSheet;
import com.kpstv.youtube.fragments.LyricBottomSheet;
import com.kpstv.youtube.models.LyricModel;
import com.kpstv.youtube.models.YTConfig;
//import com.kpstv.youtube.services.DownloadService;
import com.kpstv.youtube.services.IntentDownloadService;
import com.kpstv.youtube.services.MusicService;
import com.kpstv.youtube.utils.HttpHandler;
import com.kpstv.youtube.utils.SoundCloud;
import com.kpstv.youtube.utils.YTMeta;
import com.kpstv.youtube.utils.YTStatistics;
import com.kpstv.youtube.utils.YTutils;
import com.spyhunter99.supertooltips.ToolTip;
import com.spyhunter99.supertooltips.ToolTipManager;
import com.tonyodev.fetch2.Fetch;
import com.warkiz.widget.IndicatorSeekBar;
import com.warkiz.widget.OnSeekChangeListener;
import com.warkiz.widget.SeekParams;

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

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;

import okhttp3.OkHttpClient;

public class PlayerActivity2 extends AppCompatActivity implements AppInterface {

    static String YouTubeUrl;
    static ImageView backImage,backImage1, viewImage;

    static ConstraintLayout mainlayout;

    static TextView mainTitle;
    static TextView viewCount;
    static TextView currentDuration;
    public static TextView totalDuration;
    static TextView channelTitle;

    public static Activity activity; public static ProgressBar progressBar;

    static ImageButton previousFab, playFab, nextFab, repeatButton, downloadButton, playlistButton, youTubeButton,lyricButton;

    ImageButton navigationDown, shareButton; //static VisualizerView visualizerView;

    static ViewPager mainPager;
    static PlayerAdapter adapter;

    static ImageView mainImageView;

   // static ProgressBar mprogressBar;

    static IndicatorSeekBar indicatorSeekBar;
    private static InterstitialAd mInterstitialAd;
    public static boolean doNotCallAdapter=true;
    public static ImageView favouriteButton, addToPlaylist;

    static Handler mHandler = new Handler();

    AsyncTask<String, String, String> mergeTask, cutTask, mp3Task;

    SharedPreferences preferences; boolean supportFFmpeg=false;

    static AsyncTask<Void,Void,Void> setData; static Spanned lyricText;

    int accentColor;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int height = displayMetrics.heightPixels;
        Log.e("DisplayMatrix",height+"");

        activity = this;

        setContentView(R.layout.activity_player_new);

        Rect rectangle = new Rect();
        Window window = getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
        int statusBarHeight = rectangle.top;
        int contentViewTop =
                window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
        int titleBarHeight= contentViewTop - statusBarHeight;

        accentColor = ContextCompat.getColor(this,R.color.colorAccent);

        preferences = getSharedPreferences("settings", MODE_PRIVATE);

        setTitle("");

        getAllViews();

        playFab.setOnClickListener(v -> changePlayBack(!MusicService.isplaying));

        nextFab.setOnTouchListener((v, motionEvent) -> {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                   MusicService.playNext();
                   /* if (setData!=null && setData.getStatus() == AsyncTask.Status.RUNNING)
                        setData.cancel(true);
                    if (!MusicService.localPlayBack)
                        setData = new loadData();
                    else setData = new loadData_Offline(MusicService.videoID);
                    setData.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);*/

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        previousFab.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                    MusicService.playPrevious();
                   /* if (setData!=null && setData.getStatus() == AsyncTask.Status.RUNNING)
                        setData.cancel(true);
                    setData = new loadData();
                    setData.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);*/

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        lyricButton.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                    Bundle args = new Bundle();
                    args.putSerializable("model",new LyricModel(MusicService.videoTitle,lyricText));
                    LyricBottomSheet bottomSheet = new LyricBottomSheet();
                    bottomSheet.setArguments(args);
                    bottomSheet.show(getSupportFragmentManager(),"");

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        shareButton.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                   // shareButton.setVisibility();
                    Log.e(TAG, "onCreate: ShareButtonState:"+shareButton.getVisibility());

                   if (MusicService.localPlayBack) {
                       YTutils.shareFile(PlayerActivity2.activity,new File(MusicService.videoID));
                   }else {
                       Intent intent = new Intent(Intent.ACTION_SEND);
                       intent.setType("text/plain");
                       intent.putExtra(Intent.EXTRA_TEXT,"Listen to "+MusicService.videoTitle+" by "+MusicService.channelTitle+" "+
                               YTutils.getYtUrl(MusicService.videoID));
                       activity.startActivity(Intent.createChooser(intent,"Share"));
                   }

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        indicatorSeekBar.setOnSeekChangeListener(new OnSeekChangeListener() {
            @Override
            public void onSeeking(SeekParams seekParams) {

            }

            @Override
            public void onStartTrackingTouch(IndicatorSeekBar seekBar) {
                mHandler.removeCallbacks(mUpdateTimeTask);
            }

            @Override
            public void onStopTrackingTouch(IndicatorSeekBar seekBar) {
                mHandler.removeCallbacks(mUpdateTimeTask);

                long progresstoSeek = YTutils.progressToTimer(seekBar.getProgress(), MusicService.total_duration);
                Log.e("ProgresstoSeek", progresstoSeek + "");
                MusicService.mMediaSessionCallback.onSeekTo(progresstoSeek);

                updateProgressBar();
            }
        });

        mainPager.addOnPageChangeListener(mainPageListener);

        adapter = new PlayerAdapter(activity,MusicService.yturls);
        mainPager.setAdapter(adapter);

        loadAgain();

        if (MusicService.bitmapIcon!=null) {
           try {
               Palette.generateAsync(MusicService.bitmapIcon, palette -> {
                   MusicService.nColor = palette.getVibrantColor(activity.getResources().getColor(R.color.light_white));
                   Log.e(TAG, "onCreate: Changing nColor: " + MusicService.nColor);
                   backImage.setColorFilter(MusicService.nColor);
                   backImage1.setColorFilter(MusicService.nColor);
               });
           }catch (Exception ignored){}
        }

        addToPlaylist.setOnTouchListener((v, motionEvent) -> {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageView view = (ImageView ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                    if (MusicService.total_seconds==0)
                    {
                        Toast.makeText(activity, "Player is still processing!", Toast.LENGTH_SHORT).show();
                    }else
                    YTutils.addToPlayList(activity,MusicService.videoID,MusicService.videoTitle,
                            MusicService.channelTitle,MusicService.imgUrl,MusicService.total_seconds);

                case MotionEvent.ACTION_CANCEL: {
                    ImageView view = (ImageView) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        favouriteButton.setOnTouchListener((v, motionEvent) -> {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageView view = (ImageView ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                   MusicService.actionFavouriteClicked();

                case MotionEvent.ACTION_CANCEL: {
                    ImageView view = (ImageView) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        downloadButton.setOnTouchListener((v, motionEvent) -> {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                    /** For local playback stuff */
                    if (MusicService.localPlayBack) {
                        if (MusicService.yturls.size()>1)
                            startActivity(new Intent(activity,NPlaylistActivity.class));
                    }else {
                        if (Build.VERSION.SDK_INT>Build.VERSION_CODES.M) {
                            if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                    != PackageManager.PERMISSION_GRANTED) {
                                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                        100);
                            } else showListDialog();
                        }else showListDialog();

                    }

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        downloadButton.setOnLongClickListener(view -> {
            if (IntentDownloadService.pendingJobs.size()>0) {
                Intent intent = new Intent(PlayerActivity2.this,DownloadActivity.class);
                startActivity(intent);
            }
            return true;
        });

        youTubeButton.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                    YTutils.StartURLIntent(YouTubeUrl, this);

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        playlistButton.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageButton view = (ImageButton ) v;
                    view.setColorFilter(accentColor);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:

                    if (MusicService.yturls.size()>1)
                        startActivity(new Intent(this,NPlaylistActivity.class));

                case MotionEvent.ACTION_CANCEL: {
                    ImageButton view = (ImageButton) v;
                    view.clearColorFilter();
                    view.invalidate();
                    break;
                }
            }
            return true;
        });

        repeatButton.setOnClickListener(v1->{
            switch (MusicService.repeatMode) {
                case 0:
                    MusicService.repeatMode=1;
                    Toast.makeText(activity, "Playlist will be repeated!", Toast.LENGTH_SHORT).show();
                    break;
                case 1:
                    MusicService.repeatMode = 2;
                    Toast.makeText(activity, "Current song will be repeated!", Toast.LENGTH_SHORT).show();
                    break;
                case 2:
                    MusicService.repeatMode = 0;
                    break;
            }
           // MusicService.isLoop = !MusicService.isLoop;
          //  makeRepeat(MusicService.isLoop);
            makeRepeat(MusicService.repeatMode);
        });

        navigationDown.setOnClickListener(view -> {
            callFinish();
        });

        try {
            if (!MusicService.localPlayBack) {
                String url = MusicService.yturls.get(MusicService.ytIndex);
                if (url.contains("soundcloud.com"))
                    setSoundCloudData(url);
            }
        }catch (Exception e) {
            finish();
        }

    }

    public static void setViewPagerData() {
        mainPager.removeOnPageChangeListener(mainPageListener);
        adapter = new PlayerAdapter(activity,MusicService.yturls);
        mainPager.setAdapter(adapter);
        mainPager.setCurrentItem(MusicService.ytIndex,false);
        mainPager.addOnPageChangeListener(mainPageListener);
    }

    public static void setLyricData(Spanned text) {
        if (text!=null) {
            Log.e(TAG, "setLyricData: Show data here..." +AppSettings.showLyricTooltip );
            lyricText = text;
            lyricButton.setVisibility(View.VISIBLE);
        }else {
            lyricText=null;
            lyricButton.setVisibility(View.GONE);
        }
    }

    static void setSoundCloudData(String url) {
        if (url.contains("soundcloud.com")) {
            if (setData != null && setData.getStatus() == AsyncTask.Status.RUNNING)
                setData.cancel(true);
            setData = new soundcloud_data(url);
            setData.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    }

    static ViewPager.OnPageChangeListener mainPageListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {

        }

        @Override
        public void onPageSelected(int pos) {
            try {
                Log.e(TAG, "onPageSelected: "+MusicService.yturls.get(pos) );
                if (MusicService.localPlayBack)
                    MainActivity.ChangeVideoOffline(pos);
                else
                    MainActivity.ChangeVideo(pos);
                String url = MusicService.yturls.get(pos);
                setSoundCloudData(url);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }



        @SuppressLint("StaticFieldLeak")
        @Override
        public void onPageScrollStateChanged(int i) {

        }
    };

    public static void loadAgain() {

        try {
            player_common();

            mainPager.removeOnPageChangeListener(mainPageListener);
            if (mainPager.getChildCount() != MusicService.yturls.size()) {
                adapter.notifyDataSetChanged();
            }
            if (mainPager.getCurrentItem() != MusicService.ytIndex) {
                mainPager.setCurrentItem(MusicService.ytIndex, true);
            }
            mainPager.addOnPageChangeListener(mainPageListener);

        }catch (Exception e) {
            Toast.makeText(activity, "Error: Something went wrong!", Toast.LENGTH_SHORT).show();
            activity.finish();
        }
    }

    static void player_common() {
        mainlayout.setVisibility(View.VISIBLE);
      //  mprogressBar.setVisibility(View.GONE);
        mainTitle.setText(MusicService.videoTitle);
        channelTitle.setText(MusicService.channelTitle);
        if (!MusicService.localPlayBack)
        {
            viewCount.setVisibility(View.VISIBLE);
            viewCount.setText(MusicService.viewCounts);
            viewImage.setVisibility(View.VISIBLE);
            favouriteButton.setVisibility(View.VISIBLE);
            addToPlaylist.setVisibility(View.VISIBLE);
            downloadButton.setImageDrawable(ContextCompat.getDrawable(activity,R.drawable.ic_file_download));
            youTubeButton.setVisibility(View.VISIBLE);
            playlistButton.setVisibility(View.VISIBLE);

            YouTubeUrl = YTutils.getYtUrl(MusicService.videoID);

            String data = YTutils.readContent(activity,"favourite.csv");
            if (data!=null && data.contains(MusicService.videoID)) {
                MusicService.isFavourite = true;
                favouriteButton.setImageDrawable(activity.getDrawable(R.drawable.ic_favorite_full));
            }else {
                MusicService.isFavourite=false;
                favouriteButton.setImageDrawable(activity.getDrawable(R.drawable.ic_favorite));
            }
        }else {
            viewCount.setVisibility(View.GONE);
            viewImage.setVisibility(View.GONE);
            favouriteButton.setVisibility(View.GONE);
            addToPlaylist.setVisibility(View.GONE);

            downloadButton.setImageDrawable(ContextCompat.getDrawable(activity,R.drawable.ic_playlist));

            youTubeButton.setVisibility(View.GONE);
            playlistButton.setVisibility(View.GONE);
        }

        if (MusicService.viewCounts.equals("-1")) {
            viewCount.setVisibility(View.GONE);
            viewImage.setVisibility(View.GONE);
        }else {
            viewCount.setVisibility(View.VISIBLE);
            viewImage.setVisibility(View.VISIBLE);
        }

        if (MusicService.yturls.size()>1)
            playlistButton.setEnabled(true);
        else playlistButton.setEnabled(false);

        // Loading color with animation...

        int colorTo = MusicService.nColor;
        if (backImage.getTag()!=null) {
            ChangeBackgroundColor(colorTo);
        }else {
            backImage.setColorFilter(MusicService.nColor);
            backImage1.setColorFilter(MusicService.nColor);
        }
        backImage.setTag(colorTo);

        makeRepeat(MusicService.repeatMode);

        setLyricData(MusicService.lyricText);

        totalDuration.setText(YTutils.milliSecondsToTimer(MusicService.total_duration));
        detectPlayback();
        updateProgressBar();
    }

    static void ChangeBackgroundColor(int colorTo) {
        Log.e("Animation","I am animating bro...");
        int colorFrom = (int) backImage.getTag();
        ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
        colorAnimation.setDuration(300);
        colorAnimation.addUpdateListener(animator -> backImage.setColorFilter((int) animator.getAnimatedValue()));
        colorAnimation.addUpdateListener(animator -> backImage1.setColorFilter((int) animator.getAnimatedValue()));
        colorAnimation.start();
    }

    private static final String TAG = "PlayerActivity2";


    static class soundcloud_data extends AsyncTask<Void,Void,Void> {
        SoundCloud soundCloud;String url;

        public soundcloud_data(String url) {
            this.url = url;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            if (soundCloud.getViewCount()!=null && !soundCloud.getViewCount().isEmpty()) {
                MusicService.viewCounts = YTutils.getViewCount(Long.parseLong(soundCloud.getViewCount()));
                viewImage.setVisibility(View.VISIBLE);
                viewCount.setVisibility(View.VISIBLE);
                viewCount.setText(MusicService.viewCounts);
            }
            super.onPostExecute(aVoid);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            soundCloud = new SoundCloud(url);
            soundCloud.captureViews();
            return null;
        }
    }

    static class loadData_Offline extends AsyncTask<Void,Void,Void> {
        String filePath;

        public loadData_Offline(String filePath) {
            this.filePath = filePath;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            Palette.generateAsync(MusicService.bitmapIcon, palette -> {
                MusicService.nColor = palette.getVibrantColor(activity.getResources().getColor(R.color.light_white));

                loadAgain();
                MusicService.rebuildNotification();
            });
            super.onPostExecute(aVoid);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            File f = new File(filePath);
            Uri uri = Uri.fromFile(f);
            try {
                MediaMetadataRetriever mmr = new MediaMetadataRetriever();
                mmr.setDataSource(activity,uri);
                String durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                String artist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
                String title = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);

                byte [] data = mmr.getEmbeddedPicture();

                if (artist==null) artist ="Unknown artist";
                if (title==null) title = YTutils.getVideoTitle(f.getName());

                if (title.contains("."))
                    title = title.split("\\.")[0];

                MusicService.videoTitle = title;
                MusicService.channelTitle = artist;
                MusicService.likeCounts = -1; MusicService.dislikeCounts = -1;
                MusicService.viewCounts = "-1";

                MusicService.total_seconds = Integer.parseInt(durationStr);

            }catch (Exception e) {
                // TODO: Do something when cannot played...
            }
            return null;
        }
    }

    static class loadData extends AsyncTask<Void,Void,Void> {
        @Override
        protected void onPostExecute(Void aVoid) {
            String imageUri = YTutils.getImageUrl(MusicService.yturls.get(MusicService.ytIndex));
            if (MusicService.videoID.contains("soundcloud.com"))
                imageUri = soundCloud.getModel().getImageUrl();
            Glide.with(activity.getApplicationContext())
                    .asBitmap()
                    .load(imageUri)
                    .into(new CustomTarget<Bitmap>() {
                        @Override
                        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                            Palette.generateAsync(resource, palette -> {
                                MusicService.bitmapIcon = resource;
                                MusicService.nColor = palette.getVibrantColor(activity.getResources().getColor(R.color.light_white));
                                Log.e(TAG, "loadData: Changing nColor: "+MusicService.nColor +
                                        ", ImageUri: "+MusicService.imgUrl );
                                loadAgain();
                                MusicService.rebuildNotification();
                            });
                        }

                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {

                        }
                    });

            super.onPostExecute(aVoid);
        }

        String jsonResponse(String videoID, int apinumber) {
            HttpHandler httpHandler = new HttpHandler();
            String link = "https://www.googleapis.com/youtube/v3/videos?id=" + videoID + "&key=" + API_KEYS[apinumber] + "&part=statistics";
            return httpHandler.makeServiceCall(link);
        }
        SoundCloud soundCloud;
        @Override
        protected Void doInBackground(Void... voids) {
            String videoID = MusicService.videoID;

            if (videoID.contains("soundcloud.com")) {
                soundCloud = new SoundCloud(videoID);
                if (soundCloud.getModel()==null || soundCloud.getModel().getStreamUrl()==null) {
                    return null;
                }
              //  soundCloud.captureViews();
                MusicService.soundCloudPlayBack=true;
                MusicService.videoTitle = soundCloud.getModel().getTitle();
                MusicService.channelTitle = soundCloud.getModel().getAuthorName();
                MusicService.imgUrl = soundCloud.getModel().getImageUrl();
                MusicService.likeCounts = -1; MusicService.dislikeCounts = -1;
                MusicService.viewCounts = "-1";
                /*if (soundCloud.getViewCount()!=null && !soundCloud.getViewCount().isEmpty())
                    MusicService.viewCounts =YTutils.getViewCount( Long.parseLong(soundCloud.getViewCount()));*/
                return null;
            }

            int i=0;
            int apiLength = API_KEYS.length;
            String json;
            do {
                json = jsonResponse(videoID, i);
                i++;
            }while (json.contains("\"error\":") && i<apiLength);

            YTMeta ytMeta = new YTMeta(videoID);
            if (ytMeta.getVideMeta() != null) {
                MusicService.channelTitle = YTutils.getChannelTitle(ytMeta.getVideMeta().getTitle(),
                        ytMeta.getVideMeta().getAuthor());
                MusicService.videoTitle = YTutils.setVideoTitle(ytMeta.getVideMeta().getTitle());
                MusicService.imgUrl = ytMeta.getVideMeta().getImgUrl();
            }


            if (json.contains("\"error\":")) {
                YTStatistics ytStatistics = new YTStatistics(videoID);
                MusicService.viewCounts = ytStatistics.getViewCount();
                MusicService.likeCounts = Integer.parseInt(ytStatistics.getLikeCount());
                MusicService.dislikeCounts = Integer.parseInt(ytStatistics.getDislikeCount());
                json = null;
            }

            if (json != null) {
                try {
                    JSONObject statistics = new JSONObject(json).getJSONArray("items")
                            .getJSONObject(0).getJSONObject("statistics");
                    MusicService.viewCounts = YTutils.getViewCount(Long.parseLong(statistics.getString("viewCount")));
                    MusicService.likeCounts = 100;
                    MusicService.dislikeCounts = 0;
                    try {
                        MusicService.likeCounts = Integer.parseInt(statistics.getString("likeCount"));
                        MusicService.dislikeCounts = Integer.parseInt(statistics.getString("dislikeCount"));
                    }catch (Exception e){e.printStackTrace();}

                } catch (JSONException e) {
                    e.printStackTrace();
                    Log.e("PlayerActivity_JSON", e.getMessage());
                }
            }
            return null;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 100: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    showListDialog();
                } else {
                    Toast.makeText(PlayerActivity2.this, "Permission denied!",
                            Toast.LENGTH_SHORT).show();
                }
                return;
            }
        }
    }

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

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onDestroy() {
        mHandler.removeCallbacks(mUpdateTimeTask);
        super.onDestroy();
    }

    /*@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.player_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        if (itemId == android.R.id.home) {
            callFinish();
            return true;
        } else if (itemId == R.id.action_youtube) {
            YTutils.StartURLIntent(YouTubeUrl, this);
        } else if (itemId == R.id.action_share) {
            Intent shareIntent = new Intent(Intent.ACTION_SEND);
            shareIntent.setType("text/plain");
            shareIntent.putExtra(Intent.EXTRA_TEXT, YouTubeUrl);
            startActivity(Intent.createChooser(shareIntent, "Share using..."));
        } else if (itemId == R.id.action_add) {
            YTutils.addToPlayList(this, YouTubeUrl, MusicService.total_duration / 1000);
        } else if (itemId == R.id.action_loop) {
            MusicService.isLoop = !MusicService.isLoop;
            item.setChecked(MusicService.isLoop);
        }

        return super.onOptionsItemSelected(item);
    }*/

   /* @Override
    public boolean onSupportNavigateUp() {
        Log.e("OnSupportFinished","called");
        callFinish();
        return false;
    }*/

    public void startService(YTConfig model) {
        Intent serviceIntent = new Intent(this, IntentDownloadService.class);
        serviceIntent.putExtra("addJob", model);

        ContextCompat.startForegroundService(this, serviceIntent);
    }

    public static void detectPlayback() {
        if (MusicService.isplaying)
            makePause();
        else makePlay();
    }

    public void changePlayBack(boolean isplay) {
        MusicService.changePlayBack(isplay);
        Log.e("PlayingState", "Playing State: " + MusicService.isplaying + ", isPlay:" + isplay);
        if (isplay) {
            makePause();
        } else {
            makePlay();
        }
        Log.e("CurrentDur", MusicService.player.getCurrentPosition() + "");
    }

    public static void hidePlayButton() {
        playFab.setEnabled(false);
        playFab.setColorFilter(activity.getResources().getColor(R.color.white));
    }

    public static void showPlayButton() {
        playFab.setEnabled(true);
        playFab.clearColorFilter();
    }

    public static void makePlay() {
        playFab.setImageDrawable(activity.getResources().getDrawable(R.drawable.play));
    }

    public static void makePause() {
        playFab.setImageDrawable(activity.getResources().getDrawable(R.drawable.pause));
    }

    public static void makeRepeat(int value) {
        switch (value) {
            case 0:
                repeatButton.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_repeat));
                break;
            case 1:
                repeatButton.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_repeat_true));
                break;
            case 2:
                repeatButton.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_repeat_one));
                break;
        }
       /* if (value)
            repeatButton.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_repeat_true));
        else
            repeatButton.setImageDrawable(activity.getResources().getDrawable(R.drawable.ic_repeat));*/
    }

    private void getAllViews() {
        viewImage = findViewById(R.id.imageView3);
        mainPager = findViewById(R.id.viewPager);
        lyricButton = findViewById(R.id.lyricButton);
        shareButton = findViewById(R.id.shareButton);
//        visualizerView = findViewById(R.id.visualizerView);
        favouriteButton = findViewById(R.id.favourite_button);
        progressBar = findViewById(R.id.progressBar);
        addToPlaylist = findViewById(R.id.addPlaylist_button);
        navigationDown = findViewById(R.id.navigation_down);
      //  mprogressBar = findViewById(R.id.mainprogress);
        mainTitle = findViewById(R.id.maintitle);
        viewCount = findViewById(R.id.mainviews);
        currentDuration = findViewById(R.id.currentDur);
        totalDuration = findViewById(R.id.totalDur);
        mainImageView = findViewById(R.id.mainImage);
        indicatorSeekBar = findViewById(R.id.seekBar);
        mainlayout = findViewById(R.id.mainlayout);
        backImage = findViewById(R.id.background_image);
        backImage1 = findViewById(R.id.background_image1);
        channelTitle = findViewById(R.id.channelTitle);
        youTubeButton = findViewById(R.id.youtube_IButton);

        previousFab = findViewById(R.id.previous_IButton);
        playFab = findViewById(R.id.playPause_IButton);
        nextFab = findViewById(R.id.forward_IButton);
        repeatButton = findViewById(R.id.repeat_IButton);
        downloadButton = findViewById(R.id.download_IButton);
        playlistButton = findViewById(R.id.currentPlaylist_IButton);
    }

    void callFinish() {
        String toput = "true";
        if (!MusicService.isplaying) toput = "false";
        Intent i = new Intent(this, MainActivity.class);
        i.putExtra("videoID",YouTubeUrl);
        i.putExtra("is_playing",toput);
        i.putExtra("b_title",mainTitle.getText().toString());
        i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(i);
    }

    public static void showAd() {
        if (!AppSettings.showAds)
            return;
        //TODO: Change ad unit ID, Sample ca-app-pub-3940256099942544/1033173712
        mInterstitialAd = new InterstitialAd(activity);
        mInterstitialAd.setAdUnitId("ca-app-pub-1164424526503510/4801416648");
        mInterstitialAd.loadAd(new AdRequest.Builder().addTestDevice("07153BA64BB64F7C3F726B71C4AE30B9").build());
        mInterstitialAd.setAdListener(new AdListener() {
            @Override
            public void onAdFailedToLoad(int i) {
                super.onAdFailedToLoad(i);
                Log.e(TAG, "onAdFailedToLoad: Ad failed to load: " + i);
            }

            @Override
            public void onAdLoaded() {
                super.onAdLoaded();
                mInterstitialAd.show();
            }
        });
    }


    private void showListDialog() {
        DownloadBottomSheet downloadBottomSheet = new DownloadBottomSheet();
        downloadBottomSheet.show(getSupportFragmentManager(),"");
    }

    void showListDialog2() {

        ArrayList<String> tmplist = new ArrayList<>();
        final ArrayList<YTConfig> configs = new ArrayList<>();

        for (int i = 0; i < MusicService.ytConfigs.size(); i++) {
            String text = MusicService.ytConfigs.get(i).getText();
            boolean isalreadyadded = false;
            for (int j = 0; j < tmplist.size(); j++) {
                if (tmplist.get(j).contains(text))
                    isalreadyadded = true;
            }
            if (!isalreadyadded) {
                tmplist.add(MusicService.ytConfigs.get(i).getText());
                configs.add(MusicService.ytConfigs.get(i));
            }
        }

        final String[] arrays = new String[configs.size()];
        for (int i = 0; i < configs.size(); i++) {
            arrays[i] = configs.get(i).getText();
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(PlayerActivity2.this);
        builder.setTitle("Select Media Codec");

        builder.setItems(arrays, (dialog, which) -> {

            if (AppSettings.downloadCount<=0 && AppSettings.setDownloads) {
                YTutils.showPurchaseDialog(this);
                return;
            }else if (AppSettings.setDownloads) AppSettings.downloadCount--;
            YTConfig config = configs.get(which);
            config.setVideoID(MusicService.videoID);
            config.setAudioUrl(MusicService.audioLink);
            String filename;
            if (config.getText().length() > 55) {
                filename = config.getTitle().substring(0, 55).trim() + "." + config.getExt();
            } else {
                filename = config.getChannelTitle().trim() +" - " + config.getTitle() + "." + config.getExt();
            }
            filename = filename.replaceAll("[\\\\><\"|*?%:#/]", "");
            final String fileCurrent = filename; // Using this since current filename cannot be placed as final
            if (arrays[which].contains("+ merge audio")) {
                config.setTargetName(fileCurrent.split("\\.")[0]+".mp4");
                config.setTaskExtra("mergeTask");
                startService(config);

            } else if (arrays[which].contains("Audio ")) {

                config.setTargetName(fileCurrent.split("\\.")[0]+".mp3");
                config.setTaskExtra("mp3Task");
                startService(config);

            }else
                downloadFromUrl(fileCurrent, config);

            Toast.makeText(PlayerActivity2.this, "Download started",
                    Toast.LENGTH_SHORT).show();
            showAd();
        });
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    private Fetch fetch;
    private void downloadFromUrl(String fileName, YTConfig config) {

        if (config.isAudio() && supportFFmpeg && !config.getExt().equals(".mp3")) {

            final AlertDialog.Builder alert= new AlertDialog.Builder(PlayerActivity2.this);
            alert.setIcon( android.R.drawable.ic_dialog_info);
            alert.setTitle("MP3 Conversion");
            alert.setMessage("The current sample you've selected is not an mp3 stream.\n\nDo you want to convert song into mp3?");
            alert.setPositiveButton("Yes", (dialog1, which1) -> {
                showAd();

                String targetName = fileName.split("\\.")[0]+".mp3";

                mp3Task = new MP3Task(PlayerActivity2.this,targetName,config, MusicService.videoID);
                mp3Task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,config.getUrl());
            });
            alert.setNegativeButton("No", (dialog12, which12) -> {
                //   downloadFromUrl(fileCurrent, config);

                Toast.makeText(PlayerActivity2.this, "Download started",
                        Toast.LENGTH_SHORT).show();
                showAd();
                downloadNormal(fileName,config);
            });
            alert.setNeutralButton("Cancel",null);
            alert.show();
        }else {
            downloadNormal(fileName,config);
        }
    }

    private void downloadNormal(String fileName, YTConfig config) {
        Uri uri = Uri.parse(config.getUrl());
        DownloadManager.Request request = new DownloadManager.Request(uri);
        request.setTitle(config.getTitle()+" - "+config.getChannelTitle());

        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
        DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        manager.enqueue(request);
    }

    class MP3Task extends AsyncTask<String, String, String> {

        AlertDialog alertdialog;
        View dialogView;
        TextView tview, dtview;
        ProgressBar bar; YTConfig config;
        Context con; String fileLengthString="0";YTMeta ytMeta;
        String targetName; String videoID;boolean isConverted=false;

        public MP3Task(Context context, String fileName, YTConfig config, String videoID) {
            this.con = context;
            this.targetName = fileName;
            this.config = config;
            this.videoID = videoID;
        }

        @Override
        protected void onPreExecute() {
            Log.e("ExecutingTask","true");
            LayoutInflater inflater = getLayoutInflater();
            dialogView = inflater.inflate(R.layout.alert_merger, null);
            tview = dialogView.findViewById(R.id.textView);
            dtview = dialogView.findViewById(R.id.textView_Download);
            bar = dialogView.findViewById(R.id.progressBar);
            AlertDialog.Builder alert = new AlertDialog.Builder(PlayerActivity2.this);
            alert.setTitle("Download");
            alert.setMessage("This could take a while depending upon length of audio!");
            alert.setCancelable(false);
            alert.setView(dialogView);
            alert.setNegativeButton("Cancel", (dialog, which) -> {
                mp3Task.cancel(true);
            });
            alertdialog = alert.create();
            alertdialog.show();
        }

        @Override
        protected void onProgressUpdate(String... values) {
            tview.setText(values[1]);
            if (Integer.parseInt(values[0])==-1) {
                bar.setIndeterminate(true);
                return;
            }
            bar.setIndeterminate(false);
            bar.setProgress(Integer.parseInt(values[0]));
            dtview.setText(YTutils.getSize(Long.parseLong(values[2]))+" / "+fileLengthString);
        }

        @Override
        protected void onPostExecute(String s) {
            alertdialog.dismiss();
            if (YTutils.getFile(Environment.DIRECTORY_DOWNLOADS+"/"+targetName).exists())
                Toast.makeText(con, "Download Completed", Toast.LENGTH_LONG).show();
            else Toast.makeText(con, "Download Failed", Toast.LENGTH_LONG).show();
        }

        @Override
        protected String doInBackground(String... sUrl) {
            try {

                String prefixName = config.getTitle()+"_"+config.getChannelTitle();

                File mp3 = YTutils.getFile("YTPlayer/"+prefixName+".mp3");
                if (mp3.exists()) mp3.delete();
                File f = YTutils.getFile("YTPlayer/"+prefixName+".file");
                if (f.exists()) f.delete();


                String audioUrl = sUrl[0];

                // Download audio file first...
                URL url = new URL(audioUrl);
                URLConnection connection = url.openConnection();
                connection.connect();

                long fileLength = connection.getContentLength();
                fileLengthString = YTutils.getSize(fileLength);
                File root = Environment.getExternalStorageDirectory();

                DataInputStream input = new DataInputStream(url.openStream());
                DataOutputStream output = new DataOutputStream(new FileOutputStream(
                        root.getAbsolutePath() + "/YTPlayer/"+prefixName+".file"));

                byte data[] = new byte[8192];
                long total = 0;
                int count;
                while ((count = input.read(data)) != -1) {
                    total += count;
                    publishProgress(((int) (total * 100 / fileLength)) + "",
                            "Downloading Audio... 1/2",total+"");
                    output.write(data, 0, count);
                    output.flush();
                }
                output.flush();
                output.close();
                input.close();

                // Convert the audio file to mp3...

                publishProgress((-1) + "",
                        "Converting to mp3... 2/2");


              /*  FFmpeg ffmpeg = FFmpeg.getInstance(con);
                try {
                    String cmd[] = new String[] { "-y","-i",f.getPath(),mp3.getPath() };
                    // to execute "ffmpeg -version" command you just need to pass "-version"
                    ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {

                        @Override
                        public void onStart() {}

                        @Override
                        public void onProgress(String message) {}

                        @Override
                        public void onFailure(String message) {
                            isConverted=true;
                            Log.e("FailedToDownload","true");
                        }

                        @Override
                        public void onSuccess(String message) {
                            isConverted=true;
                            // We will set tag here...
                            MusicMetadataSet src_set = null;
                            try {
                                src_set = new MyID3().read(mp3);
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }

                            if (src_set == null)
                            {
                                Log.i("NULL", "NULL");
                            }
                            else
                            {
                                URL uri = null; ImageData imageData=null;
                                try {
                                    uri = new URL(YTutils.getImageUrlID(videoID));
                                    Bitmap bitmap = BitmapFactory.decodeStream(uri.openConnection().getInputStream());
                                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                                    byte[] bitmapdata = stream.toByteArray();
                                    imageData = new ImageData(bitmapdata,"image/jpeg","arun photo",1);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }

                                File dst = YTutils.getFile(Environment.DIRECTORY_DOWNLOADS+"/"+targetName);
                                MusicMetadata meta = new MusicMetadata(YTutils.getVideoTitle(config.getTitle()));
                                if (imageData!=null) {
                                    meta.addPicture(imageData);
                                }

                                meta.setAlbum(ytMeta.getVideMeta().getAuthor());
                                meta.setArtist(YTutils.getChannelTitle(config.getTitle(),config.getChannelTitle()));
                                try {
                                    new MyID3().write(mp3, dst, src_set, meta);
                                    mp3.delete();
                                } catch (UnsupportedEncodingException e) {
                                    e.printStackTrace();
                                } catch (ID3WriteException e) {
                                    e.printStackTrace();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }

                        @Override
                        public void onFinish() {}
                    });
                } catch (FFmpegCommandAlreadyRunningException e) {
                    // Handle if FFmpeg is already
                    Log.e("PlayerActivity2", "doInBackground: Already Running" );
                    e.printStackTrace();
                }*/


              /*  IConvertCallback callback = new IConvertCallback() {
                    @Override
                    public void onSuccess(File convertedFile) {

                    }

                    @Override
                    public void onFailure(Exception error) {
                        isConverted=true;
                        Log.e("FailedToDownload","true");
                    }
                };*/

               /* AndroidAudioConverter.with(PlayerActivity2.this)
                        .setFile(f)
                        .setFormat(AudioFormat.MP3)
                        .setCallback(callback)
                        .convert();*/

                ytMeta = new YTMeta(videoID);

                do {
                    if (mp3.exists()) {
                        total = mp3.length();
                        publishProgress(((int) (total * 100 / fileLength)) + "",
                                "Converting... 2/2",total+"");
                    }
                }while (!isConverted);

            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    class cutTask extends AsyncTask<String, String, String> {

        AlertDialog alertdialog;
        View dialogView;
        TextView tview, dtview;
        ProgressBar bar;
        Context con; String fileLengthString="0";
        String target,fileName;

        public cutTask(Context context, String targetfile) {
            this.con = context;
            this.target = targetfile;
        }

        @Override
        protected void onPreExecute() {
            Log.e("ExecutingTask","true");
            LayoutInflater inflater = getLayoutInflater();
            dialogView = inflater.inflate(R.layout.alert_merger, null);
            tview = dialogView.findViewById(R.id.textView);
            dtview = dialogView.findViewById(R.id.textView_Download);
            bar = dialogView.findViewById(R.id.progressBar);
            AlertDialog.Builder alert = new AlertDialog.Builder(PlayerActivity2.this);
            alert.setTitle("Download");
            alert.setMessage("This could take a while depending upon length of audio!");
            alert.setCancelable(false);
            alert.setView(dialogView);
            alert.setNegativeButton("Cancel", (dialog, which) -> {
                cutTask.cancel(true);
            });
            alertdialog = alert.create();
            alertdialog.show();
        }

        @Override
        protected void onProgressUpdate(String... values) {
            tview.setText(values[1]);
            if (Integer.parseInt(values[0])==-1) {
                bar.setIndeterminate(true);
                return;
            }
            bar.setIndeterminate(false);
            bar.setProgress(Integer.parseInt(values[0]));
            dtview.setText(YTutils.getSize(Long.parseLong(values[2]))+" / "+fileLengthString);
        }

        @Override
        protected void onPostExecute(String s) {
            //   Toast.makeText(PlayerActivity.this, "Saved at /sdcard/"+target, Toast.LENGTH_LONG).show();
            Log.e("FileName",fileName);
            alertdialog.dismiss();
            startEditor("file:/"+YTutils.getFile("YTPlayer/"+fileName).toString());
        }

        private void startEditor(String filePathUri) {
            Intent intent = new Intent(con, RingdroidEditActivity.class);
            intent.putExtra("FILE_PATH", filePathUri);
            startActivity(intent);
        }

        @Override
        protected String doInBackground(String... sUrl) {
            try {
                fileName = YTutils.getFile(target).getName();

                String audioUrl = sUrl[0];

                // Download audio file first...
                URL url = new URL(audioUrl);
                URLConnection connection = url.openConnection();
                connection.connect();

                long fileLength = connection.getContentLength();
                fileLengthString = YTutils.getSize(fileLength);
                File root = Environment.getExternalStorageDirectory();

                DataInputStream input = new DataInputStream(url.openStream());
                DataOutputStream output = new DataOutputStream(new FileOutputStream(
                        root.getAbsolutePath() + "/YTPlayer/"+fileName));

                byte data[] = new byte[8192];
                long total = 0;
                int count;
                while ((count = input.read(data)) != -1) {
                    total += count;
                    publishProgress(((int) (total * 100 / fileLength)) + "",
                            "Downloading Audio... 1/2",total+"");
                    output.write(data, 0, count);
                    output.flush();
                }
                output.flush();
                output.close();
                input.close();

                // Trimming audio

                /*publishProgress((-1) + "", "Trimming media... 2/2");
                Mp4Cutter mp4Cutter = new Mp4Cutter();
                mp4Cutter.startTrim(
                        YTutils.getFile("YTPlayer/audio.download"),
                        YTutils.getFile(target),
                        currentDuration, totalDuration

                );*/
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    class MergeAudioVideo extends AsyncTask<String, String, String> {

        AlertDialog alertdialog;
        View dialogView;
        TextView tview, dtview;
        ProgressBar bar; String fileLengthString;
        Context con;
        String target;

        public MergeAudioVideo(Context context, String targetfile) {
            this.con = context;
            this.target = targetfile;
        }

        @Override
        protected void onPreExecute() {
            Log.e("ExecutingTask","true");
            LayoutInflater inflater = getLayoutInflater();
            dialogView = inflater.inflate(R.layout.alert_merger, null);
            tview = dialogView.findViewById(R.id.textView);
            dtview = dialogView.findViewById(R.id.textView_Download);
            bar = dialogView.findViewById(R.id.progressBar);
            AlertDialog.Builder alert = new AlertDialog.Builder(PlayerActivity2.this);
            alert.setTitle("Merging");
            alert.setMessage("This could take a while depending upon length of video!");
            alert.setCancelable(false);
            alert.setView(dialogView);
            alert.setNegativeButton("Cancel", (dialog, which) -> {
                mergeTask.cancel(true);
            });
            alertdialog = alert.create();
            alertdialog.show();
        }
        boolean isDownloaded=false; long totalsize,currentsize,oldbytes,fileLength;
        @Override
        protected String doInBackground(String... sUrl) {
            try {

                String audioUrl = sUrl[0];
                String videoUrl = sUrl[1];

                File audio = YTutils.getFile("/YTPlayer/audio.m4a");
                if (audio.exists()) audio.delete();
                File video = YTutils.getFile("/YTPlayer/video.download");
                if (video.exists()) video.delete();

                /** Calculate total file size... */
                URL url = new URL(videoUrl);
                URLConnection connection = url.openConnection();
                connection.connect();

                fileLength = connection.getContentLength();

                /** Download audio file first... */
                url = new URL(audioUrl);
                connection = url.openConnection();
                connection.connect();

                fileLength += connection.getContentLength();
                totalsize = fileLength;

                PRDownloader.download(videoUrl, YTutils.getFile("YTPlayer").getPath(), "video.mp4")
                        .build()
                        .setOnProgressListener(progress -> {
                            currentsize = progress.currentBytes;
                            if (totalsize==0)
                                return;
                            publishProgress(((int) (totalsize * 100 / fileLength)) + "",
                                    "Downloading Audio... 1/3");
                       //     setProgress((int) (progress.currentBytes * 100 / totalsize),false);
                            oldbytes = currentsize;
                        })
                        .start(new OnDownloadListener() {
                            @Override
                            public void onDownloadComplete() {
                                Log.e(TAG, "onDownloadComplete: Audio Download Complete" );

                                /** Download video file now... */
                                PRDownloader.download(audioUrl,YTutils.getFile("YTPlayer").getPath(),"audio.m4a")
                                        .build()
                                        .setOnProgressListener(progress1 -> {
                                            currentsize = oldbytes+progress1.currentBytes;
                                         //   setProgress((int) ((progress1.currentBytes + oldbytes) * 100 / totalsize),false);
                                        })
                                        .start(new OnDownloadListener() {
                                            @Override
                                            public void onDownloadComplete() {
                                                Log.e(TAG, "onDownloadComplete: Video Download Complete" );



                                                   /* muxing(YTutils.getFile("YTPlayer/video.mp4").getPath(),
                                                            YTutils.getFile("YTPlayer/audio.m4a").getPath(),
                                                            save.getPath());*/

                                                /** Show notification... */


                                                isDownloaded=true;
                                            }

                                            @Override
                                            public void onError(Error error) {
                                                isDownloaded=true;
                                            }
                                        });
                            }

                            @Override
                            public void onError(Error error) {
                                isDownloaded=true;
                            }

                        });

                do {} while (!isDownloaded);

                // Merging audio and video third
                publishProgress((-1) + "", "Merging media... 3/3");
                mux("/sdcard/YTPlayer/video.download","/sdcard/YTPlayer/audio.download",
                        target);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            tview.setText(values[1]);
            if (Integer.parseInt(values[0])==-1) {
                bar.setIndeterminate(true);
                return;
            }
            bar.setIndeterminate(false);
            bar.setProgress(Integer.parseInt(values[0]));
            dtview.setText(YTutils.getSize(Long.parseLong(values[2]))+" / "+fileLengthString);
        }

        @Override
        protected void onPostExecute(String s) {
            Toast.makeText(PlayerActivity2.this, "Saved at "+target, Toast.LENGTH_LONG).show();
            alertdialog.dismiss();
        }

        public boolean mux(String videoFile, String audioFile, String outputFile) {
            Movie video;
            try {
                video = new MovieCreator().build(videoFile);
            } catch (RuntimeException e) {
                e.printStackTrace();
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }

            Movie audio;
            try {

                audio = new MovieCreator().build(audioFile);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            } catch (NullPointerException e) {
                e.printStackTrace();
                return false;
            }

            Track audioTrack = audio.getTracks().get(0);
            video.addTrack(audioTrack);
            Container out = new DefaultMp4Builder().build(video);
            FileOutputStream fos;
            try {
                fos = new FileOutputStream(outputFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return false;
            }

            BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
            try {
                out.writeContainer(byteBufferByteChannel);
                byteBufferByteChannel.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }


    }

    class BufferedWritableFileByteChannel implements WritableByteChannel {
        //    private static final int BUFFER_CAPACITY = 1000000;
        private static final int BUFFER_CAPACITY = 10000000;

        private boolean isOpen = true;
        private final OutputStream outputStream;
        private final ByteBuffer byteBuffer;
        private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];

        private void dumpToFile() {
            try {
                outputStream.write(rawBuffer, 0, byteBuffer.position());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        private BufferedWritableFileByteChannel(OutputStream outputStream) {
            this.outputStream = outputStream;
            this.byteBuffer = ByteBuffer.wrap(rawBuffer);
        }

        @Override
        public int write(ByteBuffer inputBuffer) {
            int inputBytes = inputBuffer.remaining();

            if (inputBytes > byteBuffer.remaining()) {
                dumpToFile();
                byteBuffer.clear();

                if (inputBytes > byteBuffer.remaining()) {
                    throw new BufferOverflowException();
                }
            }

            byteBuffer.put(inputBuffer);

            return inputBytes;
        }

        @Override
        public boolean isOpen() {
            return isOpen;
        }

        @Override
        public void close() throws IOException {
            dumpToFile();
            isOpen = false;
        }
    }

    public static void updateProgressBar() {
        mHandler.postDelayed(mUpdateTimeTask, 100);
    }

    public static Runnable mUpdateTimeTask = new Runnable() {
        public void run() {

            long totalDuration = MusicService.player.getDuration();
            long currentDur = MusicService.player.getCurrentPosition();

            // Displaying time completed playing
            currentDuration.setText("" + YTutils.milliSecondsToTimer(currentDur));

            // Updating progress bar
            int progress = (YTutils.getProgressPercentage(currentDur, totalDuration));
            //Log.d("Progress", ""+progress);
            indicatorSeekBar.setProgress(progress);

            // Running this thread after 100 milliseconds
            mHandler.postDelayed(this, 100);
        }
    };
}