package fr.Skydust.JdrBot.jukebox;

import fr.Skydust.JdrBot.cmds.playmusic.PlayMusic;
import fr.Skydust.JdrBot.menu.Menu;
import fr.Skydust.JdrBot.menu.MenuSystem;
import fr.Skydust.JdrBot.utils.UnicodeEmotes;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;

import java.io.File;
import java.util.*;

public class JukeboxSystem {
    // Const
    public static final String initialFolder = "Songs";
    public static final String musicPlayerThumbnail = "https://cd4.iconfinder.com/data/icons/miu/24/device-volume-loudspeaker-speaker-up-glyph-128.png";

    // Dyn
    // Keeping track of the song currently played to update menus accordingly
    // Example : "Songs/Spell Temps/2"
    public String songPlayedPath = "";

    private final HashMap<String, Menu> linkedPath = new HashMap<>();
    public Message jukeboxMessage;

    private String currentFolder = "";

    public void load(Message msg) {
        jukeboxMessage = msg;
        openFolder(initialFolder);
    }

    public void openFolder(String newPath) {
        currentFolder = newPath;

        // If the menu to this path is not created, make and register it.
        Menu menu = linkedPath.get(currentFolder);

        if(menu == null) {
            List<String> items = new ArrayList<>();
            File[] files = new File(currentFolder).listFiles();

            // If it isn't the root folder, place the return button
            if(isntInRootFolder()) {
                items.add(UnicodeEmotes.ReturnUnicode + " Retour");
            }
            if(files != null) {
                // Sort files by alphabetical order with directories first
                Arrays.sort(files, sortItemsComp);

                /*
                 * Makes this style
                 * 0️⃣ 📁 Directory
                 * 1️⃣ 🎵 Song
                 * 2️⃣ 🔉 Played Song
                 */
                for (File file : files) {
                    if(!file.getName().startsWith(".")) { // Ignore Unix hidden files
                        StringBuilder sb = new StringBuilder();

                        if (file.isDirectory())
                            sb.append(UnicodeEmotes.FolderUnicode);
                        else
                            sb.append(UnicodeEmotes.SongUnicode);

                        sb.append(" ");
                        sb.append(file.getName().replaceAll(".mp3", ""));

                        items.add(sb.toString());
                    }
                }
            }

            menu = new Menu("Music Player 4000", "Choisis la musique :", musicPlayerThumbnail, items.toArray(new String[0])) {
                @Override
                public void onButtonClicked(Member member, Message msg, int itemId) {
                    if(itemId >= items.length)
                        return;

                    String str = items[itemId];

                    // Loop back to open a subfolder
                    if (str.contains(UnicodeEmotes.FolderUnicode)) {
                        openFolder(currentFolder + "/" + getFileNameFromItem(str));
                        return;
                    }

                    // Return button
                    if (isntInRootFolder() && itemId == 0) {
                        // Back one menu
                        String subFolder = currentFolder.substring(0,  currentFolder.lastIndexOf("/"));
                        currentFolder = subFolder;
                        MenuSystem.changeMenu(msg, linkedPath.get(subFolder));
                        return;
                    }

                    // If not already playing
                    if (str.contains(UnicodeEmotes.SongUnicode)) {
                        if(!songPlayedPath.equals("")) {
                            String folder = songPlayedPath.substring(0,  songPlayedPath.lastIndexOf("/"));
                            int previousSongItemID = Integer.parseInt(songPlayedPath.substring(songPlayedPath.lastIndexOf("/")+1));

                            Menu previousMenu = linkedPath.get(folder);
                            previousMenu.items[previousSongItemID] =
                                    previousMenu.items[previousSongItemID].replace(
                                            UnicodeEmotes.PlayUnicode,
                                            UnicodeEmotes.SongUnicode
                                    );
                        }
                        items[itemId] = items[itemId].replace(UnicodeEmotes.SongUnicode, UnicodeEmotes.PlayUnicode);

                        String songPath = currentFolder + "/" + getFileNameFromItem(str) + ".mp3";

                        PlayMusic.loadAndPlay(msg.getGuild(), (TextChannel) msg.getChannel(), songPath, true, true);

                        // Format: Songs/Folder/SubFolder/2
                        songPlayedPath = currentFolder + "/" + itemId;
                    } else {
                        //If already playing, stop the song
                        items[itemId] = items[itemId].replace(UnicodeEmotes.PlayUnicode, UnicodeEmotes.SongUnicode);
                        PlayMusic.getGuildAudioPlayer(member.getGuild()).scheduler.stop();
                    }
                    // Reload the current menu
                    MenuSystem.reloadMenu(msg);
                }
            };
            linkedPath.put(currentFolder, menu);
        }

        // Reget the message to update it
        Menu finalMenu = menu;
        jukeboxMessage.getChannel().retrieveMessageById(jukeboxMessage.getIdLong()).queue(msg -> {
                    MenuSystem.changeMenu(msg, finalMenu);
                });
    }

    public boolean isntInRootFolder() {
        return !currentFolder.equals(initialFolder);
    }

    public static String getFileNameFromItem(String item) {
        return item.split(" ", 2)[1];
    }

    private final Comparator<File> sortItemsComp = (o1, o2) -> {
        if (o1.isDirectory() && !o2.isDirectory()) return -1; // Directory before non-directory
        else if (!o1.isDirectory() && o2.isDirectory()) return 1; // Non-directory after directory
        else return o1.compareTo(o2); // Alphabetic order otherwise
    };
}
