package elements;

import elements.exceptions.ReadErrorChatException;
import elements.exceptions.ReadErrorListException;
import elements.exceptions.SaveErrorChatException;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by Guillermo Serrahima on 4/14/16.
 */
public class Persistence {
    private static Persistence persistence;

    private Persistence() {

    }

    public static Persistence getInstance() {
        if(persistence == null) persistence = new Persistence();
        return persistence;
    }

    private void saveChatInfo(Chat c) throws SaveErrorChatException {
        Path file;
        List<String> lines = c.saveInfo();

        try {
            file = Paths.get("geiserFiles/" + c.getChatId() + "/chat_info.txt");
            if (!Files.exists(file.getParent()))
                Files.createDirectories(file.getParent());
            Files.write(file, lines, Charset.forName("UTF-8"));
        } catch (IOException e) {
            throw new SaveErrorChatException(e);
        }
    }

    private Chat loadChatInfo(long chat_id) throws ReadErrorChatException {
        Path file = Paths.get("geiserFiles/" + chat_id + "/chat_info.txt");
        List<String> lines;

        try {
            lines = Files.readAllLines(file);
        } catch (IOException e) {
            throw new ReadErrorChatException(e);
        }

        return new Chat(lines);
    }

    private void saveChatLists(Chat c) throws SaveErrorChatException {
        Path file;
        ArrayList<List<String>> lists = c.saveLists();

        for(int i = 0; i < lists.size(); i++) {
            List<String> lines = lists.get(i);
            String filename = lines.get(1);
            lines.remove(1);

            try {
                file = Paths.get("geiserFiles/" + c.getChatId() + "/lists/" + filename + ".txt");

                if (!Files.exists(file.getParent()))
                    Files.createDirectories(file.getParent());
                Files.write(file, lines, Charset.forName("UTF-8"));
            } catch (IOException e) {
                throw new SaveErrorChatException(e);
            }
        }
    }

    private void loadChatLists(Chat c) throws ReadErrorChatException, ReadErrorListException {
        Path file;
        ArrayList<List<String>> lists;
        List<String> lines;

        try {
            List<Path> files = Files.walk(Paths.get("geiserFiles/" + c.getChatId() + "/lists/"), 1).collect(Collectors.toList());

            for(int i = 0; i < files.size(); i++) {
                file = files.get(i);
                String filename = file.getFileName().toString();
                if(filename.endsWith(".txt")) {
                    System.out.println("Reading " + filename);

                    lines = Files.readAllLines(file);
                    filename = filename.substring(0,filename.length() - 4);
                    c.loadList(filename, lines);
                }
            }
        } catch (IOException e) {
            throw new ReadErrorChatException(e);
        }
    }

    public void saveChat(Chat c) throws SaveErrorChatException {
        //Save chat stats
        saveChatInfo(c);

        //Save chat lists
        saveChatLists(c);
    }

    public void saveChatIndex(Map<Long, Chat> chats) throws SaveErrorChatException {
        Path file;
        ArrayList<String> lines = new ArrayList<String>();

        Iterator<Map.Entry<Long, Chat>> it = chats.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry<Long, Chat> entry = it.next();

            lines.add(entry.getKey() + "=" + entry.getValue().getName());
        }

        try {
            file = Paths.get("geiserFiles/chat_index.txt");
            if (!Files.exists(file.getParent()))
                Files.createDirectories(file.getParent());
            Files.write(file, lines, Charset.forName("UTF-8"));
        } catch (IOException e) {
            throw new SaveErrorChatException(e);
        }
    }

    public HashMap<Long, Chat> readChats() throws ReadErrorChatException, ReadErrorListException {
        HashMap<Long, Chat> chats = new HashMap<Long, Chat>();
        Path file = Paths.get("geiserFiles/chat_index.txt");

        if (!Files.exists(file))
            return chats;

        List<String> lines;

        try {
            lines = Files.readAllLines(file);
        } catch (IOException e) {
            throw new ReadErrorChatException(e);
        }

        chats = new HashMap<Long, Chat>();

        for (int i = 0; i < lines.size(); i++) {
            String[] parse = lines.get(i).split("=");
            if (parse.length != 2) throw new ReadErrorChatException("There was a problem reading the chat index.");

            Chat c = loadChatInfo(Long.parseLong(parse[0]));
            loadChatLists(c);

            chats.put(c.getChatId(), c);
        }

        return chats;
    }
}
