package com.rks.musicx.misc.utils;

import android.Manifest;
import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.ColorStateList;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.media.MediaScannerConnection;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.Media;
import android.provider.MediaStore.MediaColumns;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.PermissionChecker;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.graphics.Palette;
import android.support.v7.view.ActionMode;
import android.support.v7.view.StandaloneActionMode;
import android.support.v7.widget.AppCompatTextView;
import android.support.v7.widget.PopupMenu;
import android.text.Html;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.afollestad.appthemeengine.Config;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.rks.musicx.MusicXApplication;
import com.rks.musicx.R;
import com.rks.musicx.data.loaders.DefaultSongLoader;
import com.rks.musicx.data.model.Album;
import com.rks.musicx.data.model.Artist;
import com.rks.musicx.data.model.Folder;
import com.rks.musicx.data.model.Song;
import com.rks.musicx.database.FavHelper;
import com.rks.musicx.database.SaveQueueDatabase;
import com.rks.musicx.interfaces.Action;
import com.rks.musicx.interfaces.ExtraCallback;
import com.rks.musicx.interfaces.RefreshData;
import com.rks.musicx.ui.activities.MainActivity;
import com.rks.musicx.ui.adapters.FolderAdapter;
import com.rks.musicx.ui.adapters.SongListAdapter;
import com.rks.musicx.ui.fragments.AlbumFragment;
import com.rks.musicx.ui.fragments.ArtistFragment;
import com.rks.musicx.ui.fragments.FavFragment;
import com.rks.musicx.ui.fragments.TagEditorFragment;

import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.CannotWriteException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagException;
import org.jaudiotagger.tag.TagOptionSingleton;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import uk.co.chrisjenx.calligraphy.CalligraphyConfig;

import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static com.rks.musicx.misc.utils.Constants.BlackTheme;
import static com.rks.musicx.misc.utils.Constants.DarkTheme;
import static com.rks.musicx.misc.utils.Constants.Four;
import static com.rks.musicx.misc.utils.Constants.LightTheme;
import static com.rks.musicx.misc.utils.Constants.One;
import static com.rks.musicx.misc.utils.Constants.Three;
import static com.rks.musicx.misc.utils.Constants.Two;
import static com.rks.musicx.misc.utils.Constants.Zero;
import static com.rks.musicx.misc.utils.Constants.fileExtensions;

/*
 * Created by Coolalien on 24/03/2017.
 */

/*
 * ©2017 Rajneesh Singh
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class Helper {

    private static ValueAnimator colorAnimation;
    private static HashMap<String, Typeface> fontCache = new HashMap<>();
    private Context context;

    public Helper(Context context) {
        this.context = context;
    }

    public static void setRingTone(Context context, String path) {
        if (permissionManager.isWriteSettingsGranted(context)) {
            setRingtone(context, path);
            Toast.makeText(context, "Ringtone set", Toast.LENGTH_SHORT).show();
        } else {
            Log.d("Helper", "Write Permission Not Granted on mashmallow+");
            Toast.makeText(context, "Settings write permission denied", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Set Ringtone
     *
     * @param context
     * @param path
     */
    private static void setRingtone(Context context, String path) {
        if (path == null) {
            return;
        }
        File file = new File(path);
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaColumns.DATA, file.getAbsolutePath());
        String filterName = path.substring(path.lastIndexOf("/") + 1);
        contentValues.put(MediaColumns.TITLE, filterName);
        contentValues.put(MediaColumns.MIME_TYPE, "audio/mp3");
        contentValues.put(MediaColumns.SIZE, file.length());
        contentValues.put(Media.IS_RINGTONE, true);
        Uri uri = MediaStore.Audio.Media.getContentUriForPath(path);
        Cursor cursor = context.getContentResolver().query(uri, null, MediaStore.MediaColumns.DATA + "=?", new String[]{path}, null);
        if (cursor != null && cursor.moveToFirst() && cursor.getCount() > 0) {
            String id = cursor.getString(0);
            contentValues.put(MediaStore.Audio.Media.IS_RINGTONE, true);
            context.getContentResolver().update(uri, contentValues, MediaStore.MediaColumns.DATA + "=?", new String[]{path});
            Uri newuri = ContentUris.withAppendedId(uri, Long.valueOf(id));
            try {
                RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, newuri);
            } catch (Throwable t) {
                t.printStackTrace();
            }
            cursor.close();
        }
    }

    /**
     * Share Music
     *
     * @param id
     * @param context
     */
    public static void shareMusic(long id, Context context) {
        if (permissionManager.isExternalReadStorageGranted(context)) {
            if (id == 0) {
                return;
            }
            Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            Uri trackUri = Uri.parse(uri.toString() + "/" + id);
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.putExtra(Intent.EXTRA_STREAM, trackUri);
            intent.setType("audio/*");
            context.startActivity(Intent.createChooser(intent, context.getString(R.string.share)));
        } else {
            Log.d("Helper", "Permission failed");
        }
    }

    /**
     * Song Details
     *
     * @param context
     * @param title
     * @param album
     * @param artist
     * @param trackno
     * @param data
     */
    public static void detailMusic(Context context, String title, String album, String artist,
                                   int trackno, String data) {
        if (data != null) {
            File file = new File(data);
            if (file.exists()) {
                float cal = (file.length() / 1024);
                String content = context.getText(R.string.song_Name) +
                        title +
                        "\n\n" +
                        context.getText(R.string.album_name) +
                        album +
                        "\n\n" +
                        context.getString(R.string.artist_name) +
                        artist +
                        "\n\n" +
                        context.getText(R.string.trackno) +
                        trackno +
                        "\n\n" +
                        context.getText(R.string.file_path) +
                        data +
                        "\n\n" +
                        context.getText(R.string.file_size) +
                        String.valueOf(String.format("%.2f", cal / 1024)) +
                        " MB";
                new MaterialDialog.Builder(context)
                        .title(R.string.action_details)
                        .content(content)
                        .positiveText(R.string.okay)
                        .typeface(getFont(context), getFont(context))
                        .onPositive((materialDialog, dialogAction) -> materialDialog.dismiss())
                        .show();
            } else {
                Toast.makeText(context, "File path not found", Toast.LENGTH_SHORT).show();
            }
        } else {
            Log.d("Helper", "path not found");
        }

    }


    /**
     * Return alpha color
     *
     * @param color
     * @param ratio
     * @return
     */
    public static int getColorWithAplha(int color, float ratio) {
        int transColor;
        int alpha = Math.round(Color.alpha(color) * ratio);
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);
        transColor = Color.argb(alpha, r, g, b);
        return transColor;
    }

    /**
     * Edit Song Tags
     *
     * @param context
     * @param song
     * @return
     */
    public static boolean editSongTags(Context context, Song song) {
        File f = new File(song.getmSongPath());
        if (f.exists()) {
            try {
                AudioFile audioFile = AudioFileIO.read(f);
                if (audioFile == null) {
                    return false;
                }
                TagOptionSingleton.getInstance().setAndroid(true);
                Tag tag = audioFile.getTag();
                if (tag == null) {
                    return false;
                }
                String year = song.getYear();
                String title = song.getTitle();
                String album = song.getAlbum();
                String artist = song.getArtist();
                String lyrics = song.getLyrics();
                tag.deleteField(FieldKey.LYRICS);
                tag.setField(FieldKey.LYRICS, Html.fromHtml(lyrics).toString());
                ContentValues values = new ContentValues();
                if (title != null){
                    tag.setField(FieldKey.TITLE, title);
                    values.put(MediaStore.Audio.Media.TITLE, title);
                }
                if (artist != null){
                    tag.setField(FieldKey.ARTIST, artist);
                    values.put(MediaStore.Audio.Media.ARTIST, artist);
                }
                if (album != null){
                    tag.setField(FieldKey.ALBUM, album);
                    Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, new String[]{BaseColumns._ID,
                                    MediaStore.Audio.AlbumColumns.ALBUM, MediaStore.Audio.AlbumColumns.ALBUM_KEY,
                                    MediaStore.Audio.AlbumColumns.ARTIST}, MediaStore.Audio.AlbumColumns.ALBUM + " = ?",
                            new String[]{album}, MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);

                    if (cursor != null && cursor.moveToFirst()) {
                        long id = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
                        values.put(MediaStore.Audio.Media.ALBUM_ID, id);
                        cursor.close();
                    } else {
                        values.put(MediaStore.Audio.Media.ALBUM, album);
                    }
                }
                if (song.getTrackNumber() != -1){
                    tag.setField(FieldKey.TRACK, String.valueOf(song.getTrackNumber()));
                    values.put(MediaStore.Audio.Media.TRACK, song.getTrackNumber());
                }
                if (year != null && year.length() > 0){
                    tag.setField(FieldKey.YEAR,  "" + year);
                    values.put(MediaStore.Audio.Media.YEAR, year);
                }
                if (values.size() > 0) {
                    context.getContentResolver().update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values, android.provider.MediaStore.Audio.Media._ID + "=?", new String[]{String.valueOf(song.getId())});
                }else {
                    return false;
                }
                audioFile.setTag(tag);
                AudioFileIO.write(audioFile);
            } catch (CannotReadException | CannotWriteException | InvalidAudioFrameException | TagException | IOException | ReadOnlyFileException e) {
                e.printStackTrace();
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * Animate View
     *
     * @param view
     * @return
     */
    public static Animator[] getAnimator(View view) {
        return new Animator[]{
                ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
        };
    }

    /**
     * Fragment Transition
     *
     * @param activity
     * @param firstFragment
     * @param secondFragment
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static void setFragmentTransition(MainActivity activity, Fragment firstFragment, Fragment secondFragment, View view, String name, String tag) {
        if (activity == null) {
            return;
        }

        FragmentManager fragmentManager = activity.getSupportFragmentManager();

        boolean fragmentPopped = fragmentManager.popBackStackImmediate(tag, 0);

        if (fragmentPopped) {
            // fragment is pop from backStack
        } else {
            Transition transitionFade = TransitionInflater.from(activity).inflateTransition(R.transition.change_image_transform);
            Transition transitionImage = TransitionInflater.from(activity).inflateTransition(R.transition.change_image_transform);

            firstFragment.setSharedElementReturnTransition(transitionImage);
            firstFragment.setEnterTransition(transitionFade);
            firstFragment.setExitTransition(transitionFade);

            secondFragment.setSharedElementEnterTransition(transitionImage);
            secondFragment.setEnterTransition(transitionFade);
            secondFragment.setExitTransition(transitionFade);

            fragmentManager.beginTransaction()
                    .replace(R.id.container, secondFragment)
                    .addSharedElement(view, name)
                    .addToBackStack(tag)
                    .commit();
        }
    }

    /**
     * Filter String
     *
     * @param str
     * @return
     */
    public static String stringFilter(String str) {
        if (str == null) {
            return null;
        }
        Pattern lineMatcher = Pattern.compile("\\n[\\\\/:*?\\\"<>|]((\\[\\d\\d:\\d\\d\\.\\d\\d\\])+)(.+)");
        Matcher m = lineMatcher.matcher(str);
        return m.replaceAll("").trim();
    }


    /**
     * Create App directory
     *
     * @param direName
     * @return
     */
    public static String createAppDir(String direName) {
        File file = new File(Environment.getExternalStorageDirectory() + "/" + "MusicX", direName);
        if (!file.exists()) {
            file.mkdirs();
        }
        return null;
    }

    /**
     * Rotate ImageView
     *
     * @param view
     */
    public static void rotationAnim(@NonNull View view) {
        RotateAnimation rotateAnimation1 = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        rotateAnimation1.setInterpolator(new LinearInterpolator());
        rotateAnimation1.setDuration(300);
        rotateAnimation1.setRepeatCount(0);
        view.startAnimation(rotateAnimation1);
    }

    /**
     * Return Array with palette color
     *
     * @param context
     * @param palette
     * @return
     */
    public static int[] getAvailableColor(Context context, Palette palette) {
        int[] temp = new int[3]; //array with size 3
        if (palette.getVibrantSwatch() != null) {
            temp[0] = palette.getVibrantSwatch().getRgb();
            temp[1] = palette.getVibrantSwatch().getTitleTextColor();
            temp[2] = palette.getVibrantSwatch().getBodyTextColor();
        } else if (palette.getMutedSwatch() != null) {
            temp[0] = palette.getMutedSwatch().getRgb();
            temp[1] = palette.getMutedSwatch().getTitleTextColor();
            temp[2] = palette.getMutedSwatch().getBodyTextColor();
        } else if (palette.getDarkVibrantSwatch() != null) {
            temp[0] = palette.getDarkVibrantSwatch().getRgb();
            temp[1] = palette.getDarkVibrantSwatch().getTitleTextColor();
            temp[2] = palette.getDarkVibrantSwatch().getBodyTextColor();
        } else if (palette.getDarkMutedSwatch() != null) {
            temp[0] = palette.getDarkMutedSwatch().getRgb();
            temp[1] = palette.getDarkMutedSwatch().getTitleTextColor();
            temp[2] = palette.getDarkMutedSwatch().getBodyTextColor();
        } else if (palette.getDominantSwatch() != null) {
            temp[0] = palette.getDominantSwatch().getRgb();
            temp[1] = palette.getDominantSwatch().getTitleTextColor();
            temp[2] = palette.getDominantSwatch().getBodyTextColor();
        } else {
            String atkey = Helper.getATEKey(context);
            int accent = Config.accentColor(context, atkey);
            temp[0] = accent;
            temp[1] = 0xffe5e5e5;
            temp[2] = accent;
        }
        return temp;
    }

    /**
     * Theme Config
     * @param context
     * @return
     */
    public static String getATEKey(Context context) {
        if (MusicXApplication.getmPreferences() == null) {
            return null;
        }
        Boolean theme = MusicXApplication.getmPreferences().getBoolean(DarkTheme, false);
        Boolean blacktheme = MusicXApplication.getmPreferences().getBoolean(BlackTheme, false);
        if (theme) {
            SharedPreferences.Editor editor = MusicXApplication.getmPreferences().edit();
            editor.putBoolean(BlackTheme, false);
            editor.apply();
            return DarkTheme;
        } else if (blacktheme) {
            SharedPreferences.Editor editor = MusicXApplication.getmPreferences().edit();
            editor.putBoolean(DarkTheme, false);
            editor.apply();
            return BlackTheme;
        } else {
            return LightTheme;
        }
    }

    /**
     * Filter Artist ArrayList
     *
     * @param artistlist
     * @param query
     * @return
     */
    public static List<Artist> filterArtist(List<Artist> artistlist, String query) {
        query = query.toLowerCase().trim();
        final List<Artist> filterartistlist = new ArrayList<>();
        for (Artist artist : artistlist) {
            final String text = artist.getName().toLowerCase().trim();
            if (text.contains(query)) {
                filterartistlist.add(artist);
            }
        }
        return filterartistlist;
    }

    /**
     * Filter Album
     *
     * @param albumList
     * @param query
     * @return
     */
    public static List<Album> filterAlbum(List<Album> albumList, String query) {
        query = query.toLowerCase();
        final List<Album> filteralbumlist = new ArrayList<>();
        for (Album album : albumList) {
            final String text = album.getAlbumName().toLowerCase().trim();
            if (text.contains(query)) {
                filteralbumlist.add(album);
            }
        }
        return filteralbumlist;
    }

    /**
     * GuideLines Dialog
     *
     * @param context
     */
    public static void GuidLines(Context context) {
        MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
        builder.title("GuideLines");
        WebView webView = new WebView(context);
        webView.loadUrl("file:///android_asset/Guidlines.html");
        builder.positiveText(android.R.string.ok);
        builder.typeface(getFont(context),getFont(context));
        builder.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                dialog.dismiss();
            }
        });
        builder.customView(webView, false);
        builder.build();
        builder.show();
    }

    /**
     * GuideLines Dialog
     *
     * @param context
     */
    public static void LyricsApi(Context context) {
        MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
        builder.title("Lyrics Api");
        WebView webView = new WebView(context);
        webView.loadUrl("file:///android_asset/Lyrics_api.html");
        builder.positiveText(android.R.string.ok);
        builder.typeface(getFont(context), getFont(context));
        builder.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                dialog.dismiss();
            }
        });
        builder.customView(webView, false);
        builder.build();
        builder.show();
    }
    /**
     * ChangeLogs Dialog
     *
     * @param context
     */
    public static void Changelogs(Context context) {
        MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
        builder.title("Changelogs");
        WebView webView = new WebView(context);
        webView.loadUrl("file:///android_asset/app_changelogs.html");
        builder.positiveText(android.R.string.ok);
        builder.typeface(getFont(context), getFont(context));
        builder.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                dialog.dismiss();
            }
        });
        builder.customView(webView, false);
        builder.build();
        builder.show();
    }

    /**
     * Licenses Dialog
     *
     * @param context
     */
    public static void Licenses(Context context) {
        MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
        builder.title("Licenses");
        WebView webView = new WebView(context);
        webView.loadUrl("file:///android_asset/licenses.html");
        builder.negativeText(android.R.string.cancel);
        builder.positiveText(android.R.string.ok);
        builder.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                builder.autoDismiss(true);
            }
        });
        builder.onNegative(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                builder.cancelable(true);
            }
        });
        builder.customView(webView, false);
        builder.build();
        builder.show();
    }

    public static String shortTime(Context context, long secs) {
        long hours, mins;
        hours = secs / 3600;
        secs %= 3600;
        mins = secs / 60;
        secs %= 60;
        final String durationFormat = context
                .getString(hours == 0 ? R.string.durationformatshort : R.string.durationformatlong);
        return String.format(durationFormat, hours, mins, secs);
    }

    /**
     * Show Rate Dailog
     *
     * @param mContext
     */
    public static void showRateDialog(final Context mContext) {
        final MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext);
        String appName = mContext.getString(R.string.app_name);
        builder.title("Rate " + appName);
        builder.content("If you enjoy using " + appName
                + ", please take a moment to rate it. Thanks for your support!");
        builder.negativeText(mContext.getString(android.R.string.cancel));
        builder.positiveText(mContext.getString(android.R.string.ok));
        builder.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                mContext.startActivity(new Intent(Intent.ACTION_VIEW,
                        Uri.parse("https://play.google.com/store/apps/details?id=com.rks.musicx")));
            }
        });
        builder.typeface(getFont(mContext),getFont(mContext));
        builder.onNegative(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                builder.autoDismiss(true);
            }
        });
        builder.dismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                dialogInterface.dismiss();
            }
        });
        builder.show();
    }

    /**
     * Return Storage Path
     *
     * @return
     */
    public static String getStoragePath() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String musicfolderpath = Environment.getExternalStorageDirectory().getAbsolutePath();
            Log.d("Helper", musicfolderpath);
            return musicfolderpath;
        } else {
            return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
        }
    }

    /**
     * Return text As bitmap
     *
     * @param text
     * @param textSize
     * @param textColor
     * @return
     */
    public static Bitmap textAsBitmap(String text, float textSize, int textColor) {
        Paint paint = new Paint(ANTI_ALIAS_FLAG);
        paint.setTextSize(textSize); //text size
        paint.setColor(textColor); //text color
        paint.setTextAlign(Paint.Align.LEFT); //align center
        float baseline = -paint.ascent(); // ascent() is negative
        int width = (int) (paint.measureText(text) + 0.0f); // round
        int height = (int) (baseline + paint.descent() + 0.0f);
        Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(image);
        canvas.drawText(text, 0, baseline, paint); //draw text
        return image;
    }

    /**
     * Duration Calculator
     * @param id
     * @return
     */
    public static String durationCalculator(long id) {
        String finalTimerString = "";
        String secondsString = "";
        String mp3Minutes = "";
        // Convert total duration into time

        int minutes = (int) (id % (1000 * 60 * 60)) / (1000 * 60);
        int seconds = (int) ((id % (1000 * 60 * 60)) % (1000 * 60) / 1000);

        // Prepending 0 to seconds if it is one digit
        if (seconds < 10) {
            secondsString = "0" + seconds;
        } else {
            secondsString = "" + seconds;
        }
        if (minutes < 10) {
            mp3Minutes = "0" + minutes;
        } else {
            mp3Minutes = "" + minutes;
        }
        finalTimerString = finalTimerString + mp3Minutes + ":" + secondsString;
        // return timer string
        return finalTimerString;
    }

    /**
     * Multi file delete
     * @param songList
     * @param context
     */
    public static void multiDeleteTrack(Action action, List<Song> songList, Context context) {
        if (songList.size() == 0) {
            return;
        }
        MaterialDialog.Builder dialog = new MaterialDialog.Builder(context);
        dialog.title("Delete Tracks");
        dialog.content(context.getString(R.string.delete_music));
        dialog.positiveText(android.R.string.ok);
        dialog.typeface(getFont(context), getFont(context));
        dialog.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                boolean confirm = false;
                for (Song song : songList) {
                    String path = song.getmSongPath();
                    if (path != null) {
                        File file = new File(path);
                        if (file.exists()) {
                            if (file.delete()) {
                                confirm = true;
                                MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, new String[]{"audio/*"}, new MediaScannerConnection.MediaScannerConnectionClient() {
                                    @Override
                                    public void onMediaScannerConnected() {

                                    }

                                    @Override
                                    public void onScanCompleted(String s, Uri uri) {
                                        action.refresh();
                                    }
                                });
                            } else {
                                confirm = false;
                            }

                        }
                    }
                }
                if (confirm) {
                    Log.e("Helper", "files are Deleted");
                    action.refresh();
                    Toast.makeText(context, "All Songs deleted", Toast.LENGTH_SHORT).show();
                } else {
                    Log.e("Helper", "files are not Deleted");
                    action.refresh();
                    Toast.makeText(context, "Failed to delete song", Toast.LENGTH_SHORT).show();
                }
            }
        });
        dialog.negativeText(R.string.cancel);
        dialog.show();
    }

    /**
     * Folder Menu
     *
     * @param context
     * @param view
     */
    public static void showFolderMenu(Context context, View view, File file, RefreshData refreshData) {
        PopupMenu popupMenu = new PopupMenu(context, view);
        MenuInflater menuInflater = popupMenu.getMenuInflater();
        menuInflater.inflate(R.menu.folder_menu, popupMenu.getMenu());
        if (file == null) {
            return;
        }
        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.exclude_folder:
                        excludeFolder(context, file, refreshData);
                        break;
                }
                return false;
            }
        });
        popupMenu.show();
    }

    /**
     * Exclude folder
     *
     * @param context
     * @param file
     */
    private static void excludeFolder(Context context, File file, RefreshData refreshData) {
        if (permissionManager.writeExternalStorageGranted(context)) {
            if (file == null) {
                return;
            }
            String path = file.getAbsolutePath();
            int lastIndexOf = path.lastIndexOf("/");
            path = path.substring(0, lastIndexOf);
            Log.e("Helper", path);
            String exlude = path + "/" + "." + file.getName();
            File dist = new File(exlude);
            Log.e("Helper", file.getName());
            Log.e("Helper", dist.getName());
            Log.e("Helper", file.getAbsolutePath());
            Log.e("Helper", dist.getAbsolutePath());
            boolean exclude = file.renameTo(dist);
            if (exclude) {
                Toast.makeText(context, "Folder excluded", Toast.LENGTH_SHORT).show();
                refreshData.refresh();
            } else {
                Toast.makeText(context, "Folder exclude failed", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public static int parseToInt(String maybeInt, int defaultValue) {
        if (maybeInt == null) return defaultValue;
        maybeInt = maybeInt.trim();
        if (maybeInt.isEmpty()) return defaultValue;
        return Integer.parseInt(maybeInt);
    }

    /**
     * Return Index of songList in the folderSection
     *
     * @param path
     * @param songList
     * @return
     */
    public static int getIndex(@NonNull String path, @NonNull List<Song> songList) {
        int index = -1;
        for (int i = 0; i < songList.size(); i++) {
            Song song = songList.get(i);
            if (song.getmSongPath().contains(path)) {
                index = i;
                Log.e("Helper", String.valueOf(index));
                break;
            }
        }
        return index;
    }

    /**
     * AlbumArtwork Location
     *
     * @return
     */
    public static String getAlbumArtworkLocation() {
        return Environment.getExternalStorageDirectory() + "/MusicX/" + ".AlbumArtwork/";
    }

    /**
     * ArtistArtwork Location
     *
     * @return
     */
    public static String getArtistArtworkLocation() {
        return Environment.getExternalStorageDirectory() + "/MusicX/" + ".ArtistArtwork/";
    }

    /**
     * Return Lyrics Directory
     *
     * @return
     */
    public static String getDirLocation() {
        return Environment.getExternalStorageDirectory() + "/MusicX/" + "Lyrics/";
    }

    /**
     * Set fileName
     *
     * @param title
     * @return
     */
    static String setFileName(String title) {
        if (TextUtils.isEmpty(title)) {
            title = "unknown";
        }
        return title;
    }

    /**
     * Animate view's background color
     *
     * @param view
     * @param colorBg
     */
    public static void animateViews(Context context, View view, int colorBg) {
        colorAnimation = setAnimator(0xffe5e5e5, colorBg);
        colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                view.setBackgroundColor((Integer) animator.getAnimatedValue());
            }

        });
        colorAnimation.start();
    }

    private static ValueAnimator setAnimator(int colorFrom, int colorTo) {
        ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
        long duration = 300;
        colorAnimation.setDuration(duration);
        return colorAnimation;
    }

    /**
     * Font
     * @param context
     * @param path
     */
    public static void getCalligraphy(Context context, String path) {
        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                .setDefaultFontPath(path)
                .addCustomStyle(AppCompatTextView.class, android.R.attr.textViewStyle)
                .addCustomStyle(TextView.class, android.R.attr.textViewStyle)
                .addCustomStyle(EditText.class, android.R.attr.editTextStyle)
                .setFontAttrId(R.attr.fontPath)
                .build());
        Extras.getInstance().saveTypeface(path);
    }

    /**
     * Start Activity
     * @param context
     * @param sClass
     * @param <S>
     */
    public static <S> void startActivity(Activity context, Class<S> sClass){
        if (context == null){
            return;
        }
        Intent intent = new Intent(context, sClass);
        context.startActivity(intent);
    }

    /**
     * Delete Directory
     * @param fileOrDirectory
     */
    public static void deleteRecursive(Context context, File fileOrDirectory) {
        if (permissionManager.writeExternalStorageGranted(context)) {
            if (fileOrDirectory != null) {
                if (fileOrDirectory.isDirectory()) {
                    boolean issuccess = fileOrDirectory.delete();
                    if (issuccess) {
                        Log.d("Helper", "delete Success");
                    } else {
                        Log.d("Helper", "delete failed");
                    }
                }
            }
       }
    }

    /**
     * return Typeface
     * @param context
     * @return
     */
    public static Typeface getFont(Context context) {
        String path = Extras.getInstance().getTypeface();
        return getTypeface(context, path);
    }

    /**
     * Typeface
     * @param customFont
     * @return
     */
    public static Typeface getTypeface(Context context, String customFont) {
        Typeface tf = fontCache.get(customFont);
        if(tf == null) {
            try {
                tf = Typeface.createFromAsset(context.getAssets(), customFont);
            } catch (Exception e) {
                return null;
            }
            fontCache.put(customFont, tf);
        }
        return tf;
    }

    /**
     * Rotate view 360
     * @param view
     */
    public static void rotateFab(@NonNull View view){
        ViewCompat.animate(view).
                rotation(360f).
                withLayer().
                setDuration(300).
                setInterpolator(new FastOutSlowInInterpolator()).
                start();
    }

    /**
     * check activity/class/package present or not in the device
     * @param context
     * @param intent
     * @return
     */
    public static boolean isActivityPresent(Context context, Intent intent){
        List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        return list.size() > 0;
    }

    /**
     * Set color to nav and status bar
     * @param activity
     * @param v
     */
    public static void setColor(@NonNull Activity activity, int color,View v){
        if (activity.getWindow() == null){
            return;
        }
        if (Extras.getInstance().getDarkTheme() || Extras.getInstance().getBlackTheme()) {
            activity.getWindow().setStatusBarColor(color);
            v.setBackgroundColor(color);
            activity.getWindow().setNavigationBarColor(color);
        } else {
            activity.getWindow().setStatusBarColor(color);
            v.setBackgroundColor(color);
            activity.getWindow().setNavigationBarColor(color);
        }
    }

    /***
     * Filter AudioFile Length
     * @return
     */
    public static String filterAudio(){
        String filterAudio = "15000";
        switch (Extras.getInstance().getAudioFilter()){
            case Zero:
                filterAudio = "30000"; //30sec
                break;
            case One:
                filterAudio = "60000"; //1min
                break;
            case Two:
                filterAudio = "120000"; //2min
                break;
            case Three:
                filterAudio = "180000"; //3min
                break;
            case Four:
                filterAudio = "240000"; //4min
                break;
            case "5":
                filterAudio = "300000"; //5min
                break;
        }
        return filterAudio;
    }

    /**
     * Set background color os actionmode using reflection
     * @param actionMode
     * @param color
     */
    public static void setActionModeBackgroundColor(ActionMode actionMode, int color) {
        try {
            StandaloneActionMode standaloneActionMode = (StandaloneActionMode) actionMode;
            Field mContextView = StandaloneActionMode.class.getDeclaredField("mContextView");
            mContextView.setAccessible(true);
            Object value = mContextView.get(standaloneActionMode);
            ((View) value).setBackground(new ColorDrawable(color));
        } catch (Throwable ignore) {
            ignore.printStackTrace();
        }
    }
    
    /**
     * return song metadata from path
     * @param context
     * @param path
     * @return
     */
    public static List<Song> getSongMetaData(Context context, String path) {
        if (path == null){
            return null;
        }
        List<Song> songList = new ArrayList<>();
        DefaultSongLoader defaultSongLoader = new DefaultSongLoader(context);
        defaultSongLoader.setProvider(true);
        defaultSongLoader.setUri(Uri.parse(String.valueOf(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)));
        defaultSongLoader.setQueryTable(null);
        for (String ext : fileExtensions) {
            if (path.toLowerCase().endsWith(ext)) {
                defaultSongLoader.setSelection(MediaStore.Audio.Media.DATA + " like ? ");
                defaultSongLoader.setQueryTable2(new String[]{"%" + path + "%"});
                defaultSongLoader.setSortOrder(null);
                songList.add(defaultSongLoader.getSongData());
            }
        }
        return songList;
    }

    public static Song getSongData(String sortOrder, @NonNull Context context, String path) {
        if (path == null) {
            return null;
        }
        Song song = new Song();
        if (PermissionChecker.checkCallingOrSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PermissionChecker.PERMISSION_GRANTED) {
            Cursor cursor = context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, null, MediaStore.Audio.Media.DATA + " like ? ", new String[]{"%" + path + "%"}, sortOrder);
            if (cursor != null && cursor.moveToFirst()) {
                int idCol = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
                int titleCol = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
                int artistCol = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
                int albumCol = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
                int albumIdCol = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
                int trackCol = cursor.getColumnIndex(MediaStore.Audio.Media.TRACK);
                int datacol = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);

                /**
                 * @return songs metadata
                 */
                long id = cursor.getLong(idCol);
                String title = cursor.getString(titleCol);
                String artist = cursor.getString(artistCol);
                String album = cursor.getString(albumCol);
                long albumId = cursor.getLong(albumIdCol);
                int track = cursor.getInt(trackCol);
                String mSongPath = cursor.getString(datacol);

                song.setAlbum(album);
                song.setmSongPath(mSongPath);
                song.setArtist(artist);
                song.setId(id);
                song.setAlbumId(albumId);
                song.setTrackNumber(track);
                song.setTitle(title);
            }
            if (cursor != null) {
                cursor.close();
            }
        } else {
            Log.e("DefaultSongLoader", "No read permissions");
        }
        return song;
    }

    /**
     * ActionMode Config
     * @param mainActivity
     * @param context
     * @param action
     * @return
     */
    public static ActionMode.Callback getActionCallback(MainActivity mainActivity, Context context, Action action, boolean whichAdapter, ExtraCallback extraCallback) {
        if (mainActivity == null){
            return null;
        }
        android.support.v7.view.ActionMode.Callback mActionModeCallback = new android.support.v7.view.ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(android.support.v7.view.ActionMode mode, Menu menu) {
                MenuInflater menuInflater = mode.getMenuInflater();
                menuInflater.inflate(R.menu.multi_select, menu);
                return true;
            }

            @Override
            public boolean onPrepareActionMode(android.support.v7.view.ActionMode mode, Menu menu) {
                return false;
            }

            @Override
            public boolean onActionItemClicked(android.support.v7.view.ActionMode mode, MenuItem item) {

                switch (item.getItemId()){
                    case R.id.action_add_to_playlist:
                        if (whichAdapter) {
                            PlaylistHelper.PlaylistMultiChooser(action.currentFrag(), context, getSelectedSong(extraCallback.songlistAdapter()));
                        } else {
                            PlaylistHelper.PlaylistMultiChooser(action.currentFrag(), context, getSelectedSong(extraCallback.folderAdapter()));
                        }
                        break;
                    case R.id.action_add_to_queue:
                        try {
                            if (whichAdapter) {
                                for (Song song : getSelectedSong(extraCallback.songlistAdapter())) {
                                    mainActivity.addToQueue(song);
                                }
                            } else {
                                for (Song song : getSelectedSong(extraCallback.folderAdapter())) {
                                    mainActivity.addToQueue(song);
                                }
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            Toast.makeText(context, "Added to queue", Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case R.id.action_play:
                        if (whichAdapter) {
                            mainActivity.onShuffleRequested(getSelectedSong(extraCallback.songlistAdapter()), true);
                        } else {
                            mainActivity.onShuffleRequested(getSelectedSong(extraCallback.folderAdapter()), true);
                        }
                        break;
                    case R.id.action_delete:
                        if (whichAdapter) {
                            multiDeleteTrack(action, getSelectedSong(extraCallback.songlistAdapter()), context);
                        } else {
                            multiDeleteTrack(action, getSelectedSong(extraCallback.folderAdapter()), context);
                        }
                        break;
                }
                return true;
            }

            @Override
            public void onDestroyActionMode(android.support.v7.view.ActionMode mode) {
                action.clear();
            }


        };
        return mActionModeCallback;
    }

    /**
     * MultiSelection SongList
     * @return
     */
    private static List<Song> getSelectedSong(SongListAdapter songListAdapter) {
        if (songListAdapter == null || songListAdapter.getSelectedItems().size() == 0){
            return null;
        }
        List<Integer> selectedPos = songListAdapter.getSelectedItems();
        List<Song> songList = new ArrayList<>();
        int pos;
        for (int i = selectedPos.size() -1; i>=0; i--){
            pos = selectedPos.get(i);
            Song song = songListAdapter.getItem(pos);
            songList.add(song);
        }
        return songList;
    }

    /**
     * MultiSelection SongList
     *
     * @return
     */
    private static List<Song> getSelectedSong(FolderAdapter folderAdapter) {
        if (folderAdapter == null || folderAdapter.getSelectedItems().size() == 0) {
            return null;
        }
        List<Integer> selectedPos = folderAdapter.getSelectedItems();
        List<Song> songList = new ArrayList<>();
        int pos;
        for (int i = selectedPos.size() - 1; i >= 0; i--) {
            pos = selectedPos.get(i);
            Song song = folderAdapter.getSongList().get(pos);//getItem(pos);
            songList.add(song);
        }
        return songList;
    }

    /**
     * Return Saved QuequeList
     * @param context
     * @return
     */
    public static List<String> getSavedQueueList(Context context){
        List<String> queueList = new ArrayList<>();
        SaveQueueDatabase queueDatabase = new SaveQueueDatabase(context, Constants.Queue_Store_TableName);
        queueList = queueDatabase.readAll();
        queueDatabase.close();
        if (queueList.size() > 0){
            return queueList;
        }else {
            return null;
        }
    }

    /**
     * Filter space EditText
     *
     * @return
     */
    @NonNull
    public static InputFilter inputFilter() {
        return new InputFilter() {
            @Override
            public CharSequence filter(CharSequence charSequence, int start, int end, Spanned spanned, int i2, int i3) {
                String filter = "";
                for (int k = start; k < end; k++) {
                    char chz = charSequence.charAt(k);
                    if (!Character.isWhitespace(chz)) {
                        filter += chz;
                    }
                }
                return filter;
            }
        };
    }

    /**
     * Color Helper
     */

    @ColorInt
    public static int getTitleTextColor(@ColorInt int color) {
        double darkness = 1.0D - (0.299D * (double) Color.red(color) + 0.587D * (double) Color.green(color) + 0.114D * (double) Color.blue(color)) / 255.0D;
        return darkness < 0.35D ? getDarkerColor(color, 0.25F) : -1;
    }

    @ColorInt
    public static int getBodyTextColor(@ColorInt int color) {
        int title = getTitleTextColor(color);
        return setColorAlpha(title, 0.7F);
    }

    @ColorInt
    public static int getDarkerColor(@ColorInt int color, @FloatRange(from = 0.0D, to = 1.0D) float transparency) {
        float[] hsv = new float[3];
        Color.colorToHSV(color, hsv);
        hsv[2] *= transparency;
        return Color.HSVToColor(hsv);
    }

    @ColorInt
    public static int setColorAlpha(@ColorInt int color, @FloatRange(from = 0.0D, to = 1.0D) float alpha) {
        int alpha2 = Math.round((float) Color.alpha(color) * alpha);
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        return Color.argb(alpha2, red, green, blue);
    }

    public static ColorStateList getColorStateList(@ColorInt int color) {
        int[][] states = new int[][]{{16842919}, {16842908}, new int[0]};
        int[] colors = new int[]{getDarkerColor(color, 0.8F), getDarkerColor(color, 0.8F), color};
        return new ColorStateList(states, colors);
    }

    public static boolean isValidColor(String string) {
        try {
            Color.parseColor(string);
            return true;
        } catch (Exception var2) {
            return false;
        }
    }

    @NonNull
    public static Intent imagePicker(Context context) {
        if (permissionManager.isExternalReadStorageGranted(context)) {
            Intent chooser = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            chooser.setType("image/*");
            Intent intent = Intent.createChooser(chooser, "Choose image");
            return intent;
        } else {
            Toast.makeText(context, "Permission grant failed", Toast.LENGTH_SHORT).show();
            return null;
        }
    }

    /**
     * return real path of image
     *
     * @param uri
     * @param context
     * @return
     */
    public static String getRealPathFromURI(Uri uri, Context context) {
        if (uri == null) {
            return null;
        }
        String[] projection = {MediaStore.Images.Media.DATA};
        Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
        if (cursor != null) {
            int column_index = cursor
                    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            String path = cursor.getString(column_index);
            cursor.close();
            return path;
        }
        return uri.getPath();
    }

    @NonNull
    public static Animator getCircularShowAnimtion(@NonNull View view) {
        int cx = view.getWidth() / 2;
        int cy = view.getHeight() / 2;
        int finalRadius = (int) Math.hypot(view.getWidth(), view.getHeight());
        Animator animation = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, finalRadius);
        animation.setDuration(500);
        return animation;
    }

    @NonNull
    public static Animator getCircularHideAnimtion(@NonNull View view) {
        int cx = view.getWidth() / 2;
        int cy = view.getHeight() / 2;
        int finalRadius = (int) Math.hypot(view.getWidth(), view.getHeight());
        Animator animation = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, finalRadius);
        animation.setDuration(500);
        return animation;
    }

    /**
     * Delete Track
     *
     * @param name
     * @param path
     * @param context
     */
    public void DeleteTrack(RefreshData refreshData, String name, String path, Context context) {
        MaterialDialog.Builder dialog = new MaterialDialog.Builder(context);
        dialog.title(name);
        dialog.content(R.string.delete_music);
        dialog.positiveText(android.R.string.ok);
        dialog.typeface(getFont(context),getFont(context));
        dialog.onPositive(new MaterialDialog.SingleButtonCallback() {
            @Override
            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                if (path != null) {
                    File file = new File(path);
                    if (file.exists()) {
                        if (file.delete()) {
                            Log.e("-->", "file Deleted :" + path);
                            MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, new String[]{"audio/*"}, new MediaScannerConnection.MediaScannerConnectionClient() {
                                @Override
                                public void onMediaScannerConnected() {

                                }

                                @Override
                                public void onScanCompleted(String s, Uri uri) {
                                    refreshData.refresh();
                                }
                            });
                            Toast.makeText(context, "Song deleted", Toast.LENGTH_SHORT).show();
                        } else {
                            Log.e("-->", "file not Deleted :" + name);
                            refreshData.refresh();
                            Toast.makeText(context, "Failed to delete song", Toast.LENGTH_SHORT).show();
                        }

                    } else {
                        refreshData.refresh();
                    }
                } else {
                    Log.d("Helper", "Path not found");
                }

            }
        });
        dialog.negativeText(R.string.cancel);
        dialog.show();
    }

    /**
     * Song Menu Options
     *
     * @param torf
     * @param activity
     * @param v
     * @param context
     */
    public void showMenu(boolean torf, RefreshData refreshData, MainActivity activity, View v, Context context, Song song) {
        PopupMenu popup = new PopupMenu(context, v);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.song_list_item, popup.getMenu());
        // Song song = songListAdapter.getItem(position);
        FavHelper favHelper = new FavHelper(context);
        popup.getMenu().findItem(R.id.action_remove_playlist).setVisible(torf);
        if (activity == null){
            return;
        }
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_remove_playlist:
                        PlaylistHelper.deletePlaylistTrack(context, Extras.getInstance().getPlaylistId(), song.getId());
                        Toast.makeText(context, "Removed from playlist", Toast.LENGTH_SHORT).show();
                        refreshData.refresh();
                        break;
                    case R.id.action_add_to_queue:
                        activity.addToQueue(song);
                        Toast.makeText(context, "Added to queue", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.action_set_as_next_track:
                        activity.setAsNextTrack(song);
                        Toast.makeText(context, "Added to next", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.action_add_to_playlist:
                        PlaylistHelper.PlaylistChooser(refreshData.currentFrag(), context, song.getId());
                        break;
                    case R.id.action_addFav:
                        new FavHelper(context).addFavorite(song.getId());
                        Toast.makeText(context, "Added to fav", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.action_edit_tags:
                        Extras.getInstance().saveMetaData(song);
                        activity.setFragment(TagEditorFragment.getInstance());
                        break;
                    case R.id.action_set_ringtone:
                        setRingTone(context, song.getmSongPath());
                        Toast.makeText(context, "Ringtone set", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.action_delete:
                        DeleteTrack(refreshData, song.getTitle(), song.getmSongPath(), context);
                        break;
                    case R.id.action_details:
                        detailMusic(context, song.getTitle(), song.getAlbum(), song.getArtist(),
                                song.getTrackNumber(), song.getmSongPath());
                        break;
                    case R.id.action_share:
                        Helper.shareMusic(song.getId(), context);
                        break;
                    case R.id.action_fav:
                        activity.setFragment(FavFragment.newFavoritesFragment());
                        break;
                    case R.id.action_removeFav:
                        if (favHelper.isFavorite(song.getId())) {
                            favHelper.removeFromFavorites(song.getId());
                            Toast.makeText(context, "Removed from fav", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(context, "First add to fav", Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case R.id.go_to_album:
                        Album album = new Album();
                        album.setAlbumName(song.getAlbum());
                        album.setArtistName(song.getArtist());
                        album.setYear(0);
                        album.setTrackCount(song.getTrackNumber());
                        album.setId(song.getAlbumId());
                        activity.setFragment(AlbumFragment.newInstance(album));
                        break;
                    case R.id.go_to_artist:
                        Artist artist = new Artist(song.getArtistId(), song.getArtist(), 0, 0);
                        activity.setFragment(ArtistFragment.newInstance(artist));
                        break;
                }
                return false;
            }
        });
        popup.show();
    }

    // End of color Helper

    /**
     * ArtistImage  load
     *
     * @param name
     * @return
     */
    public String loadArtistImage(String name) {
        return getArtistArtworkLocation() + setFileName(name) + ".jpeg";
    }

    /**
     * AlbumImage  load
     *
     * @param name
     * @return
     */
    public String loadAlbumImage(String name) {
        return getAlbumArtworkLocation() + setFileName(name) + ".jpeg";
    }

    /**
     * Filter Song List
     *
     * @param songList
     * @param query
     * @return
     */
    public List<Song> filter(List<Song> songList, String query) {
        query = query.toLowerCase().trim();
        final List<Song> filtersonglist = new ArrayList<>();
        for (Song song : songList) {
            final String text = song.getTitle().toLowerCase().trim();
            if (text.contains(query)) {
                Log.e("Helper", "Query --> search song");
                filtersonglist.add(song);
            }
        }
        return filtersonglist;
    }

    /**
     * Filter Folder
     *
     * @param fileList
     * @param query
     * @return
     */
    public List<Folder> filterFolder(@NonNull Context context,  List<Folder> fileList, String query) {
        query = query.toLowerCase().trim();
        final List<Folder> filterFolder = new ArrayList<>();
        final List<Song> songList = new ArrayList<>();
        for (Folder folder : fileList) {
            Folder folders = new Folder();
            if (!folder.getFile().isDirectory()) {
                Song song = Helper.getSongData(Extras.getInstance().getSongSortOrder(), context, folder.getFile().getAbsolutePath());
                final String text = song.getTitle().toLowerCase().trim();
                if (text.contains(query)) {
                    songList.add(song);
                }
            }
            final String text1 = folder.getFile().getName().toLowerCase().trim();
            if (text1.contains(query)) {
                folders.setFile(folder.getFile());
                folders.setSongList(songList);
                filterFolder.add(folders);
            }
        }
        return filterFolder;
    }
}