package com.reyansh.audio.audioplayer.free.FileDirectory;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
import android.widget.Toast;

import com.reyansh.audio.audioplayer.free.AsyncTasks.AsyncAddTo;
import com.reyansh.audio.audioplayer.free.Common;
import com.reyansh.audio.audioplayer.free.Dialogs.PlaylistDialog;
import com.reyansh.audio.audioplayer.free.Interfaces.OnScrolledListener;
import com.reyansh.audio.audioplayer.free.Interfaces.OnTaskCompleted;
import com.reyansh.audio.audioplayer.free.LauncherActivity.MainActivity;
import com.reyansh.audio.audioplayer.free.Models.Song;
import com.reyansh.audio.audioplayer.free.NowPlaying.NowPlayingActivity;
import com.reyansh.audio.audioplayer.free.R;
import com.reyansh.audio.audioplayer.free.Utils.HidingScrollListener;
import com.reyansh.audio.audioplayer.free.Utils.MusicUtils;
import com.reyansh.audio.audioplayer.free.Utils.PreferencesHelper;
import com.reyansh.audio.audioplayer.free.Views.DividerItemDecoration;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

public class FolderFragment extends Fragment implements View.OnClickListener, MusicUtils.Defs {
    public static final int FOLDER = 0;
    public static final int FILE = 1;
    public static final int AUDIO_FILE = 3;
    public String currentDir;
    public ArrayList<Song> fetchedFiles = new ArrayList<>();

    private final long kiloBytes = 1024;
    private final long megaBytes = kiloBytes * kiloBytes;
    private final long gigaBytes = megaBytes * kiloBytes;
    private final long teraBytes = gigaBytes * kiloBytes;

    private Common mApp;
    private Context mContext;
    private View v;
    private String rootDir;
    private List<String> fileFolderNameList = null;
    private List<String> fileFolderPathList = null;
    private List<String> fileFolderSizeList = null;
    private List<Integer> fileFolderTypeList = null;

    private HashMap<String, Parcelable> mFolderStateMap;
    private RecyclerView.LayoutManager mLayoutManager;
    private RecyclerView mRecyclerView;
    private FolderAdapter mFolderAdapter;
    private OnScrolledListener mOnScrolledListener;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        v = inflater.inflate(R.layout.file_directory, container, false);
        mContext = getActivity().getApplication();
        mApp = (Common) mContext.getApplicationContext();
        setHasOptionsMenu(true);
        mLayoutManager = new LinearLayoutManager(mContext);
        mRecyclerView = v.findViewById(R.id.recyclerView);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST, 20, 20));

        mFolderAdapter = new FolderAdapter(this);
        mRecyclerView.setAdapter(mFolderAdapter);

        mFolderStateMap = new HashMap<>();
        rootDir = PreferencesHelper.getInstance().getString(PreferencesHelper.Key.PREVIOUS_ROOT_DIR, Environment.getExternalStorageDirectory().getPath());
        currentDir = rootDir;
        getDir(currentDir, null);
        mRecyclerView.addOnScrollListener(new HidingScrollListener() {
            @Override
            public void onHide() {
                mOnScrolledListener.onScrolledUp();
            }

            @Override
            public void onShow() {
                mOnScrolledListener.onScrolledDown();
            }

        });
        return v;
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof MainActivity) {
            mOnScrolledListener = (OnScrolledListener) context;
        }
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        menu.clear();
        getActivity().getMenuInflater().inflate(R.menu.menu_playlists, menu);
    }


    @Override
    public void onDetach() {
        super.onDetach();
        mOnScrolledListener = null;
    }


    private void getDir(String dirPath, Parcelable restoreState) {
        fileFolderNameList = new ArrayList<>();
        fileFolderPathList = new ArrayList<>();
        fileFolderSizeList = new ArrayList<>();
        fileFolderTypeList = new ArrayList<>();
        final File f = new File(dirPath);
        File[] files = f.listFiles();
        if (files != null) {
            Arrays.sort(files, new FileTypeComparator());
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                if (file.canRead()) {
                    if (file.isDirectory()) {
                        String filePath;
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
                            filePath = getRealFilePath(file.getAbsolutePath());
                        else
                            filePath = file.getAbsolutePath();

                        fileFolderPathList.add(filePath);
                        fileFolderNameList.add(file.getName());
                        File[] listOfFiles = file.listFiles();

                        if (listOfFiles != null) {
                            fileFolderTypeList.add(FOLDER);
                            if (listOfFiles.length == 1) {
                                fileFolderSizeList.add("" + listOfFiles.length + " item");
                            } else {
                                fileFolderSizeList.add("" + listOfFiles.length + " items");
                            }
                        } else {
                            fileFolderTypeList.add(FOLDER);
                            fileFolderSizeList.add("Unknown items");
                        }
                    } else {
                        try {
                            String path = file.getCanonicalPath();
                            fileFolderPathList.add(path);
                        } catch (IOException e) {
                            continue;
                        }
                        fileFolderNameList.add(file.getName());
                        String fileName = "";
                        try {
                            fileName = file.getCanonicalPath();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (getFileExtension(fileName).equalsIgnoreCase("mp3")
                                || getFileExtension(fileName).equalsIgnoreCase("ogg")
                                || getFileExtension(fileName).equalsIgnoreCase("wav")
                                || getFileExtension(fileName).equalsIgnoreCase("ma4")) {

                            fileFolderTypeList.add(AUDIO_FILE);
                            fileFolderSizeList.add("" + getFormattedFileSize(file.length()));
                            String[] whereArgs = new String[]{file.getPath()};
                            fetchedFiles.add(getSongs(whereArgs));
                        } else {
                            fileFolderTypeList.add(FILE);
                            fileFolderSizeList.add("" + getFormattedFileSize(file.length()));
                        }
                    }
                }
            }
        }


        mFolderAdapter.updateData(fileFolderNameList,
                fileFolderTypeList,
                fileFolderSizeList,
                fileFolderPathList);
        if (restoreState != null) {
            mLayoutManager.onRestoreInstanceState(restoreState);
        } else if (mFolderStateMap.containsKey(dirPath)) {
            mLayoutManager.onRestoreInstanceState(mFolderStateMap.get(dirPath));
        }
        PreferencesHelper.getInstance().put(PreferencesHelper.Key.PREVIOUS_ROOT_DIR, dirPath);
    }

    public void onClick(View view, int index) {

        if (mFolderStateMap.size() == 3) {
            mFolderStateMap.clear();
        }

        mFolderStateMap.put(currentDir, mLayoutManager.onSaveInstanceState());

        String newPath = fileFolderPathList.get(index);
        if ((Integer) view.getTag(R.string.folder_list_item_type) == FOLDER)
            currentDir = newPath;
        if (fileFolderTypeList.get(index) == FOLDER) {
            fetchedFiles.clear();
            getDir(newPath, null);
        } else if (fileFolderTypeList.get(index) == AUDIO_FILE) {
            int fileIndex = 0;
            for (int i = 0; i < index; i++) {
                if (fileFolderTypeList.get(i) == AUDIO_FILE)
                    fileIndex++;
            }
            mApp.getPlayBackStarter().playSongs(fetchedFiles, fileIndex);
            startActivity(new Intent(mContext, NowPlayingActivity.class));
        } else {
            Toast.makeText(mContext, "Sorry can't open this file!!", Toast.LENGTH_SHORT).show();
        }

    }

    public String getFileExtension(String fileName) {
        String fileNameArray[] = fileName.split("\\.");
        String extension = fileNameArray[fileNameArray.length - 1];
        return extension;
    }

    @SuppressLint("SdCardPath")
    private String getRealFilePath(String filePath) {
        if (filePath.equals("/storage/emulated/0") ||
                filePath.equals("/storage/emulated/0/") ||
                filePath.equals("/storage/emulated/legacy") ||
                filePath.equals("/storage/emulated/legacy/") ||
                filePath.equals("/storage/sdcard0") ||
                filePath.equals("/storage/sdcard0/") ||
                filePath.equals("/sdcard") ||
                filePath.equals("/sdcard/") ||
                filePath.equals("/mnt/sdcard") ||
                filePath.equals("/mnt/sdcard/")) {
            return Environment.getExternalStorageDirectory().toString();
        }
        return filePath;
    }

    public String getFormattedFileSize(final long value) {
        final long[] dividers = new long[]{teraBytes, gigaBytes, megaBytes, kiloBytes, 1};
        final String[] units = new String[]{"TB", "GB", "MB", "KB", "bytes"};
        if (value < 1) {
            return "";
        }
        String result = null;
        for (int i = 0; i < dividers.length; i++) {
            final long divider = dividers[i];
            if (value >= divider) {
                result = format(value, divider, units[i]);
                break;
            }
        }
        return result;
    }

    public String format(final long value, final long divider, final String unit) {
        final double result = divider > 1 ? (double) value / (double) divider : (double) value;
        return new DecimalFormat("#,##0.#").format(result) + " " + unit;
    }

    public boolean getParentDir() {

        if (currentDir.equals("/"))
            return true;
        File currentFolder = new File(currentDir);
        String parentFolder = "";
        try {
            parentFolder = currentFolder.getParentFile().getCanonicalPath();
        } catch (Exception e) {
            e.printStackTrace();
        }
        currentDir = parentFolder;
        fetchedFiles.clear();
        getDir(parentFolder, null);
        return false;

    }

    public String getCurrentDir() {
        return currentDir;
    }


    @Override
    public void onClick(View v) {
        /*if ((v.getId() == R.id.back_imagebutton)) {
            if (getCurrentDir().equals("/")) {
            } else {
                getParentDir();
            }
        } else if (v.getId() == R.id.image_button_add) {
            if (fetchedFiles.size() != 0 && fetchedFiles != null) {
                mApp.getPlayBackStarter().addToQueue(fetchedFiles);
                Toast.makeText(mContext, fetchedFiles.size() + "Added to the queue.", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(mContext, "No songs in the current directory!!", Toast.LENGTH_SHORT).show();
            }
        }*/
    }


    public void onItemClicked(int index) {

        if (mFolderStateMap.size() == 3) {
            mFolderStateMap.clear();
        }

        mFolderStateMap.put(currentDir, mLayoutManager.onSaveInstanceState());

        String newPath = fileFolderPathList.get(index);
        if (fileFolderTypeList.get(index) == FOLDER)
            currentDir = newPath;
        if (fileFolderTypeList.get(index) == FOLDER) {
            fetchedFiles.clear();
            getDir(newPath, null);
        } else if (fileFolderTypeList.get(index) == AUDIO_FILE) {
            int fileIndex = 0;
            for (int i = 0; i < index; i++) {
                if (fileFolderTypeList.get(i) == AUDIO_FILE)
                    fileIndex++;
            }
            mApp.getPlayBackStarter().playSongs(fetchedFiles, fileIndex);
            startActivity(new Intent(mContext, NowPlayingActivity.class));
        } else {
            Toast.makeText(mContext, R.string.file_open_error, Toast.LENGTH_SHORT).show();
        }

    }

    public void refreshListView() {
        getDir(currentDir, mLayoutManager.onSaveInstanceState());
    }


    public void onPopUpMenuClickListener(View v, final int position) {

        final PopupMenu menu = new PopupMenu(getActivity(), v);
        SubMenu sub = (menu.getMenu()).addSubMenu(0, ADD_TO_PLAYLIST, 1, R.string.add_to_playlist);
        MusicUtils.makePlaylistMenu(getActivity(), sub, 0);

        menu.setOnMenuItemClickListener(item -> {
            switch (item.getItemId()) {
                case R.id.popup_song_play_next:
                    new AsyncAddTo(fetchedFiles.get(position)._title, false, fetchedFiles.get(position)).execute();
                    break;
                case R.id.popup_song_addto_queue:
                    new AsyncAddTo(fetchedFiles.get(position)._title, true, fetchedFiles.get(position)).execute();
                    break;
                case R.id.popup_song_add_to_favs:
                    mApp.getDBAccessHelper().addToFavorites(fetchedFiles.get(position));
                    break;
                case R.id.popup_song_delete:
                    ArrayList<Song> song = new ArrayList<>();
                    song.add(fetchedFiles.get(position));
                    MusicUtils.deleteFile(FolderFragment.this, song, onTaskCompleted);
                    break;
                case R.id.popup_song_use_as_phone_ringtone:
                    MusicUtils.setRingtone((AppCompatActivity) getActivity(), fetchedFiles.get(position)._id);
                    break;
                case R.id.popup_song_share:
                    MusicUtils.shareTheMusic(FolderFragment.this.getActivity(), fetchedFiles.get(position)._path);
                    break;
                case NEW_PLAYLIST:
                    PlaylistDialog playlistDialog = new PlaylistDialog();
                    Bundle bundle = new Bundle();
                    bundle.putLongArray("PLAYLIST_IDS", new long[]{fetchedFiles.get(position)._id});
                    playlistDialog.setArguments(bundle);
                    playlistDialog.show(getActivity().getSupportFragmentManager(), "FRAGMENT_TAG");
                    return true;
                case PLAYLIST_SELECTED:
                    long[] list = new long[]{fetchedFiles.get(position)._id};
                    long playlist = item.getIntent().getLongExtra("playlist", 0);
                    MusicUtils.addToPlaylist(getContext(), list, playlist);
                    return true;
            }
            return false;
        });
        menu.inflate(R.menu.popup_song);
        menu.show();
    }

    public void onFilePopUpClicked(View v, int position) {
        final PopupMenu menu = new PopupMenu(getActivity(), v);
        menu.setOnMenuItemClickListener(item -> {
            ArrayList<Song> songs = new ArrayList<>();
            Collection<File> files = FileUtils.listFiles(new File(fileFolderPathList.get(position)), new String[]{"mp3", "ma4", "ogg", "wav"}, false);

            for (File file : files) {
                songs.add(getSongs(new String[]{file.getAbsolutePath()}));
            }

            if (songs.size() == 0) {
                Toast.makeText(mContext, R.string.audio_files_not_found, Toast.LENGTH_SHORT).show();
                return false;
            }

            switch (item.getItemId()) {
                case R.id.popup_file_play:
                    mApp.getPlayBackStarter().playSongs(songs, 0);
                    startActivity(new Intent(mContext, NowPlayingActivity.class));
                    break;
                case R.id.popup_file_add_to_queue:
                    new AsyncAddTo(getString(R.string.songs_added_to_queue), true, songs).execute();
                    break;
                case R.id.popup_file_play_next:
                    new AsyncAddTo(getString(R.string.will_be_played_next), false, songs).execute();
                    break;
            }
            return false;
        });

        menu.inflate(R.menu.popup_file);
        menu.show();
    }

    public void onUpClick() {
        getParentDir();
    }

    private class FileNameComparator implements Comparator<File> {
        public int compare(File a, File b) {
            return a.getName().compareTo(b.getName());

        }
    }

    private class FileTypeComparator implements Comparator<File> {

        @Override
        public int compare(File lhs, File rhs) {
            String s1 = lhs.getName();
            String s2 = rhs.getName();
            Log.d("name", s1 + "" + s2);
            final int s1Dot = s1.lastIndexOf('.');
            final int s2Dot = s2.lastIndexOf('.');
            if ((s1Dot == -1) == (s2Dot == -1)) {
                s1 = s1.substring(s1Dot + 1);
                s2 = s2.substring(s2Dot + 1);
                return s1.compareTo(s2);
            } else if (s1Dot == -1) {
                return -1;
            } else {
                return 1;
            }
        }
    }

    private Song getSongs(String[] whereArgs) {
        Song song = null;
        String[] columns = {
                BaseColumns._ID,
                MediaStore.Audio.Media.TITLE,
                MediaStore.Audio.Media.ALBUM,
                MediaStore.Audio.Media.ALBUM_ID,
                MediaStore.Audio.Media.ARTIST,
                MediaStore.Audio.Media.ARTIST_ID,
                MediaStore.Audio.Media.DATA,
                MediaStore.Audio.Media.TRACK,
                MediaStore.Audio.Media.DURATION
        };
        Cursor cursor = getActivity().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                columns,
                MediaStore.Audio.Media.DATA + " LIKE ?", whereArgs, MediaStore.Audio.Media.TITLE);
        if (cursor != null && cursor.moveToFirst()) {
            do {
                song = new Song(
                        cursor.getLong(0),
                        cursor.getString(1),
                        cursor.getString(2),
                        cursor.getLong(3),
                        cursor.getString(4),
                        cursor.getLong(5),
                        cursor.getString(6),
                        cursor.getInt(7),
                        cursor.getLong(8));
            } while (cursor.moveToNext());
        }
        return song;
    }

    OnTaskCompleted onTaskCompleted = () -> refreshListView();
}