package Utils;

import OutputUtils.OutputRedirect;
import OutputUtils.OutputRedirect.SyncPrintOut;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.FileVisitResult;
import static java.nio.file.FileVisitResult.CONTINUE;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.swing.JOptionPane;
import static OutputUtils.OutputRedirect.SyncPrintOut.printMsg;
import static OutputUtils.OutputRedirect.SyncPrintOut.setPrintOut;
import SwingComponents.MainWindow;
import static Utils.ConvertData.convertStringToUTF8;

/**
 *
 * @author viktor penkov
 */
public abstract class FileUtils {
    public static void downloadLabels(HashMap<String, HashMap<String, String>> labels,
            String courseName, String catName, String downloadPath) throws IOException{
        
        Path rootPath = Paths.get(downloadPath, "moodleContent");
        Path categoryPath = Paths.get(rootPath.toString(), convertStringToUTF8(catName));
        Path coursePath = Paths.get(categoryPath.toString(), convertStringToUTF8(courseName));
        Path labelsPath = Paths.get(coursePath.toString(), "labels.txt");
        Files.createDirectories(coursePath);
        Iterator it = labels.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            HashMap<String, String> el = (HashMap<String, String>) pair.getValue();
            Iterator  el_it =  el.entrySet().iterator();
            while (el_it.hasNext()) {
                Map.Entry el_pair = (Map.Entry)el_it.next();
                String value = (String)el_pair.getValue();
                Files.write(labelsPath, value.getBytes(),
                        StandardOpenOption.APPEND,
                        StandardOpenOption.CREATE,
                        StandardOpenOption.WRITE);
                Files.write(labelsPath, "\n".getBytes(),
                        StandardOpenOption.APPEND,
                        StandardOpenOption.CREATE,
                        StandardOpenOption.WRITE);
            }
        }
    }
    
    public static void downloadURLS(HashMap<String, HashMap<String, String>> urls,
            String courseName, String catName, String downloadPath) throws IOException{
        Path rootPath = Paths.get(downloadPath, "moodleContent");
        Path categoryPath = Paths.get(rootPath.toString(), convertStringToUTF8(catName));
        Path coursePath = Paths.get(categoryPath.toString(), convertStringToUTF8(courseName));
        Path labelsPath = Paths.get(coursePath.toString(), "urls.txt");
        Files.createDirectories(coursePath);
        Iterator it = urls.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            HashMap<String, String> el = (HashMap<String, String>) pair.getValue();
            Iterator  el_it =  el.entrySet().iterator();
            while (el_it.hasNext()) {
                Map.Entry el_pair = (Map.Entry)el_it.next();
                String value = (String)el_pair.getValue();
                Files.write(labelsPath, value.getBytes(),
                        StandardOpenOption.APPEND,
                        StandardOpenOption.CREATE,
                        StandardOpenOption.WRITE);
                Files.write(labelsPath, "\n".getBytes(),
                        StandardOpenOption.APPEND,
                        StandardOpenOption.CREATE,
                        StandardOpenOption.WRITE);   
            }
        }
    }
    
    public static void downloadFileOrPage(HashMap<String, HashMap<String, String>> resources,
            String courseName, String catName, String downloadPath,
            String token) throws FileNotFoundException, IOException {
        Path rootPath = Paths.get(downloadPath, "moodleContent");
        Path categoryPath = Paths.get(rootPath.toString(), convertStringToUTF8(catName));
        Path coursePath = Paths.get(categoryPath.toString(), convertStringToUTF8(courseName));
        Path filesPath = Paths.get(coursePath.toString(), "files");
        Files.createDirectories(filesPath);
        Iterator it = resources.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            HashMap<String, String> el = (HashMap<String, String>) pair.getValue();
            Iterator  el_it =  el.entrySet().iterator();
            while (el_it.hasNext()) {
                Map.Entry el_pair = (Map.Entry)el_it.next();
                String value = (String)el_pair.getValue();
                String fileName = (String)el_pair.getKey();
                String downloadUrl = value + "&token=" + token;
                URL url = new URL(downloadUrl);
                ReadableByteChannel rbc = Channels.newChannel(url.openStream());
                Path currFile = Paths.get(filesPath.toString(), fileName);
                FileOutputStream fos = new FileOutputStream(currFile.toString());
                fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
                fos.close();
            }
        }
    }
    
    public static void downloadFolders(HashMap<Object, Object> dirs,
            String courseName, String catName, String downloadPath,
            String token) throws FileNotFoundException, IOException {
        Path rootPath = Paths.get(downloadPath, "moodleContent");
        Path categoryPath = Paths.get(rootPath.toString(), convertStringToUTF8(catName));
        Path coursePath = Paths.get(categoryPath.toString(), convertStringToUTF8(courseName));
        Iterator dirsIt = dirs.entrySet().iterator();
        String rootFolder = null;
        HashMap<String, HashMap<String, String>> files = null;
        while (dirsIt.hasNext()) {
            Map.Entry dirs_pair = (Map.Entry)dirsIt.next();
            rootFolder = (String)dirs_pair.getKey();
            files = (HashMap<String, HashMap<String, String>>)dirs_pair.getValue();   
        }
        Path root = Paths.get(coursePath.toString(), rootFolder);
        Files.createDirectories(root);
        
        Iterator filesIt = files.entrySet().iterator();
        while (filesIt.hasNext()) {
            Map.Entry files_it = (Map.Entry)filesIt.next();
            String subFolder_str = (String)files_it.getKey();
            HashMap<String, String> content = (HashMap<String, String>)files_it.getValue();
            Path subFolder = Paths.get(root.toString(), subFolder_str);
            Files.createDirectories(subFolder);
            Iterator content_it = content.entrySet().iterator();
            while (content_it.hasNext()) {
                Map.Entry el_pair = (Map.Entry)content_it.next();
                String value = (String)el_pair.getValue();
                String fileName = (String)el_pair.getKey();
                String downloadUrl = value + "&token=" + token;
                URL url = new URL(downloadUrl);
                ReadableByteChannel rbc = Channels.newChannel(url.openStream());
                Path currFile = Paths.get(subFolder.toString(), fileName);
                FileOutputStream fos = new FileOutputStream(currFile.toString());
                fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
                fos.close();
            }
        }
    }
    
    public static class ZipObj {
        private final ArrayList<String> fileList;
        private static final int BUFFER = 1024;
        private static String OUTPUT_ZIP_FILE;
        private static String MOODLE_SOURCE_FOLDER;
        
        
        public static String getMoodleSourceFolder() {
            return MOODLE_SOURCE_FOLDER;
        }
        
        public ZipObj(String zipFilePath, String sourcePath){
            fileList = new ArrayList<>();
            OUTPUT_ZIP_FILE = zipFilePath;
            MOODLE_SOURCE_FOLDER = sourcePath;
        }
        
        private void generateFileList(File node){
            if(node.isFile()){
                String filePath = node.getAbsolutePath();
                String fileEntry = filePath.substring(MOODLE_SOURCE_FOLDER.length()+1,
                        filePath.length());
                fileList.add(fileEntry);
            }
 
            if(node.isDirectory()){
                String[] subNode = node.list();
                for(String filename : subNode){
                    generateFileList(new File(node, filename));
		}
            }
        }
        
        private void zipIt(String zipFile) {
            byte[] buffer = new byte[BUFFER];
            try {
                FileOutputStream fos = new FileOutputStream(zipFile);
                ZipOutputStream zos = new ZipOutputStream(fos);
                for(String file : fileList) {
                    ZipEntry entry = new ZipEntry(file);
                    zos.putNextEntry(entry);
                    FileInputStream in = new FileInputStream(MOODLE_SOURCE_FOLDER + 
                            File.separator + file);
                    int len;
                    while ((len = in.read(buffer)) > 0) {
                        zos.write(buffer, 0, len);
                    }
                    in.close();
                }
                zos.closeEntry();
                zos.close();
                fos.close();
            } catch(IOException ex) {
                printMsg(ex.getMessage());
            }
        }

        public void compressContent() {
            generateFileList(new File(MOODLE_SOURCE_FOLDER));
            zipIt(OUTPUT_ZIP_FILE);
        }    
    }
    public static void removeFile(String sourcePath) throws IOException {
        DeleteFiles df = new DeleteFiles();
        Files.walkFileTree(Paths.get(sourcePath), df);
    }
    
    
    
    public static class DeleteFiles extends SimpleFileVisitor<Path> {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
            try {
                Files.delete(file);
                System.out.format("File: %s deleted!%n", convertStringToUTF8(file.toString()));
            } catch (IOException ex) {
                printMsg(ex.getMessage());
                Logger.getLogger(FileUtils.class.getName()).log(Level.SEVERE, null, ex);
            }
            return CONTINUE;
        }
        
        @Override
        public FileVisitResult postVisitDirectory(Path dir,
                                          IOException exc) {
            try {
                Files.delete(dir);
                System.out.format("Directory: %s deleted!%n", convertStringToUTF8(dir.toString()));
            } catch (IOException ex) {
                printMsg(ex.getMessage());
                Logger.getLogger(FileUtils.class.getName()).log(Level.SEVERE, null, ex);
            }
            return CONTINUE;
        }
        
        @Override
        public FileVisitResult visitFileFailed(Path file,
                                       IOException exc) {
            printMsg(exc.getMessage());
            return CONTINUE;
        }
    }
    
    public static int checkIfFolderExists(String dwpath) {
        int retVal = -1;
        if (Files.exists(Paths.get(dwpath))) {
            retVal = JOptionPane.showConfirmDialog(null,
                        "The directory already exists, overwrite?",
                        "Directory exists", JOptionPane.YES_NO_OPTION);
        }
        return retVal;
    }
}

