package de.nplusc.izc.tools.IOtools;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import de.nplusc.izc.tools.baseTools.Tools;
import java.io.*;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;

/**
 *
 * @author LH
 */
public class FileTK
{

    protected FileTK()
    {
    }

    /**
     * Erzeugt die Verzeichnisse die nötig sind um das File zuspeichern
     *
     * @param f File zum abarbeiten
     */
    public static void ensuredirExistence(File f)
    {
        File fp = f.getParentFile();
        if (!fp.exists())
        {
            fp.mkdirs();
        }
    }

    /**
     * Erzeugt die Verzeichnisse die nötig sind um das File zuspeichern
     *
     * @param path Path zum abarbeiten
     */
    public static void ensuredirExistence(String path)
    {
        ensuredirExistence(new File(path));
    }

    /**
     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
     * darunterliegende auf(begrenzt auf 40 Ebenen)
     *
     * @param path WO begonnen werden soll
     * @return Liste der Pfae
     */
    public static String[] walkDirectoryRecursively(String path)
    {
        return walkDirectoryRecursively(path, 40);
    }

    /**
     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
     * darunterliegende auf(begrenzt auf 40 Ebenen)
     *
     * @param path WO begonnen werden soll
     * @param verbose Geschwätzig?
     * @return Liste der Pfae
     */
    public static String[] walkDirectoryRecursively(String path, boolean verbose)
    {
        return walkDirectoryRecursively(path, 40, verbose);
    }

    
    
    
    
    
    /**
     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
     * darunterliegende auf
     *
     * @param path WO begonnen werden soll
     * @param recurseDepth Wieviele ebenen
     * @return Liste der Pfae
     */
    public static String[] walkDirectoryRecursively(String path, int recurseDepth)
    {
        return walkDirectoryRecursively(path, recurseDepth, false);
    }

    /**
     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
     * darunterliegende auf
     *
     * @param path WO begonnen werden soll
     * @param recurseDepth Wieviele ebenen
     * @param verbose Geschwätzig?
     * @return Liste der Pfae
     */
    public static String[] walkDirectoryRecursively(String path, int recurseDepth, boolean verbose)
    {
        //if(verbose)
        //System.out.print("cls\r\n");//DOESNTWORK:(
        ArrayList<String> data = new ArrayList<>();
        int length = 0;
        String[] DirCnt = getDirectoryContent(path);
        if(DirCnt==null)
        {
            return new String[]{};
        }
        for (String string : DirCnt)
        {
            File f = new File(string);
            if (f.isDirectory())
            {
                if (verbose)
                {
                    //System.console().
                    /*String s2 = "";//Satz mit X war wohl nix
                    while(s2.length()<length)
                    {
                        s2+="\b";//weigert sich ne zeile nauf zu gehren
                    }
                    System.out.print(s2);
                    System.console().writer().append(s2);*/
                    String s = "\rReading in:" + f.getPath();
                    
                    System.out.print(s);
                    /*try //abgekrachte FLiegenklatsche
                    {
                        Thread.sleep(20);
                    }
                    catch (InterruptedException ex)
                    {
                        ex.printStackTrace();
                    }
                            */
                    if(s.length()>length)
                    {
                        length = s.length();
                    }
                    else
                    {
                        while(s.length()<length)
                        {
                            s+=" ";//auffüllen auf gewünschte länge....
                        }
                    }
                 //   System.out.print((char)0x1b+"[u");//DOESNTWORK
                }
                String[] sdc = walkDirectoryRecursively(string, recurseDepth - 1,verbose);
                data.add(string);
                data.addAll(Arrays.asList(sdc));
            }
            else
            {
            data.add(string);
            }
        }
        String[] s = new String[]
        {
            ""
        };
        return data.toArray(s);
    }

    /**
     * Liest Dateiname mit Erweiterung aus
     * @param path Pfad derDatei
     * @return Dateiname ohne Pfad
     */
    
    public static String getFileName(String path)
    {
        //String ft1 = FileTK.getFilePath(path);
          //      Tools.DebugHelperPrint(, true, "Toolkit.enableCoreDebug");
        String ft2 = path.substring(path.lastIndexOf("\\")+1);
        //Tools.DebugHelperPrint(ft2, true, "Toolkit.enableCoreDebug");
        return ft2;
    }
    
    /**
     * Liest dateiendung aus
     *
     * @param path Dateipfad zumauslesen
     * @return dateiendung in lowercase
     */
    public static String getFileExt(String path)
    {
        String ext = null;
        int i = path.lastIndexOf('.');

        if (i > 0 && i < path.length() - 1)
        {
            ext = path.substring(i + 1).toLowerCase();
        }
        return ext;
        /*
         String[] splitpath = path.split(".");
         String ret = null;
         if(splitpath.length>1)
         {
         ret = splitpath[splitpath.length-1];
         }
         return ret;*/
    }

    /**
     * Gibt Ordnerpfad netr datei aus
     *
     * @param path Dateiname/pfd
     * @return Ordner der Datei
     */
    public static String getFilePath(String path)
    {
        path = new File(path).getAbsolutePath();//falls nen relativer Pfad verwendet wurde
        String ext = path;
        int i = path.lastIndexOf("\\");

        if (i > 0 && i < path.length())
        {
            ext = path.substring(0, i);
        }
        return ext;
    }

    private static void log(String line)
    {
        Tools.DebugHelperPrint(line, true, "Toolkit.enableCoreDebug");
    }

    /**
     * Lädt Datei in String-array
     *
     * @param path Dateipfad
     * @return ZEilenweises Array der Datei
     */
    @SuppressWarnings("ConvertToTryWithResources")
    public static String[] fileload(String path)
    {
        return fileload(path, true);
    }

    /**
     * Lädt Datei in String-array
     *
     * @param path Dateipfad
     * @param eofmark unbenutzt (zu fixen wegen bug)
     * @return ZEilenweises Array der Datei
     */
    @SuppressWarnings("ConvertToTryWithResources")
    public static String[] fileload(String path, boolean eofmark)//bugfix noch zu erledigen
    {
        String filedata = "";
        String[] filecnt;
        try
        {
            FileReader fr = new FileReader(path);
            BufferedReader br = new BufferedReader(fr);
            filedata = br.readLine() + "\n";
            String zeile = "x";
            while (zeile != null)
            {
                Tools.DebugHelperPrint(zeile, true, "Toolkit.enableFinerDebug");
                zeile = br.readLine();
                filedata = filedata + zeile + "\n";
            }
            filecnt = filedata.split("\n");
            fr.close();
        }
        catch (Exception ioe)
        {
            //log("Failed to load FIle:unknown error. Something f@ild.");
            log("noncritical internal error. Ignored");
            log(new File(path).getAbsolutePath());
            //ioe.printStackTrace();
            filecnt = new String[1];
            filecnt[0] = "LMAA";
        }
        Tools.DebugHelperPrint(filedata, true, "Toolkit.enableFinerDebug");
        return filecnt;
    }

    /**
     * Speichert Datei(überschreibend)
     *
     * @param cnt Inhalt
     * @param path Wohin
     */
    public static void writeFile(String cnt, String path)
    {
        writeFile(cnt, path, false);
    }

    /**
     * Speichert Datei
     *
     * @param cnt Inhalt
     * @param path Wohin
     * @param app Anfügen?
     */
    @SuppressWarnings("CallToThreadDumpStack")
    public static void writeFile(String cnt, String path, boolean app)
    {
        
        FileWriter fw = null;
        try
        {
            new File(path).createNewFile();
            fw = new FileWriter(path);
            if (!app)
            {
                fw.write(cnt);
            }
            else
            {
                int size = (int) new File(path).length();
                fw.write(path, size, cnt.length());
            }
        }
        catch (IOException e)
        {
            log("Konnte Datei nicht erstellen");
            e.printStackTrace();
        }
        finally
        {
            if (fw != null)
            {
                try
                {
                    fw.close();
                }
                catch (IOException e)
                {
                }
            }
        }
    }

    /**
     * Prüft auf existenz ner datei/Verzeichnis
     *
     * @param path Was
     * @return Obs existiert
     */
    public static boolean checkDirExist(String path)
    {
        File f = new File(path);
        if (!f.exists())
        {
            return false;
        }
        return true;
    }

    /**
     * entspricht dir von der cmd
     *
     * @param path Wo
     * @return Array der dateien innerhalb
     */
    public static String[] getDirectoryContent(String path)
    {
        return getDirectoryContent(path,false);
    }
        /**
     * entspricht dir von der cmd
     *
     * @param path Wo
     * @param skipPrePath ob nur die t dateinamen kommen sollen;
     * @return Array der dateien innerhalb
     */
    public static String[] getDirectoryContent(String path,boolean skipPrePath)
    {
        File f = new File(path);
        File[] dirtmpf = f.listFiles();
        //String[] dirtmp = new String[] d
        Tools.DebugHelperPrint(path, true, "Toolkit.enableFinerDebug");
        String[] ret = null;
        try
        {
            ret = new String[dirtmpf.length];

            int j;
            for (int i = 0; i < dirtmpf.length; i++)
            {
                j = i;
                String tmp = dirtmpf[i].getPath();
                if (!(tmp.length() < path.length()))
                {
                    
                    ret[j] = tmp;
                    if(skipPrePath)
                    {
                        ret[j] = getFileName(tmp);
                    }
                    
                    
                    //j++;
                }

            }
        }
        catch (NullPointerException e)
        {

            //ret = null;
            Tools.DebugHelperPrint("LMAA|" + path, true, "Toolkit.enableFinerDebug");
        }
        return ret;
    }

    /**
     * Erzeugt den relativen Pfad einer datei/eines Ordners zu eienm Basispfad
     *
     * @param absolutePath Pfad von dem relativer Pfad zu
     * @param basePath diesem ermittelt werden soll
     * @return der relative Pfad
     */
    public static String getRelativePath(String absolutePath, String basePath)//Initializer für Hack!
    {
        return getRelativePath(absolutePath, basePath, 0);
    }

    private static String getRelativePath(String absolutePath, String basePath, int recurses)//Fetter Hack wegen fehkendem Java-Befehl!
    {
        String replace = null, unRegex = null, internalPath = "", parsedPath = "";
        boolean err = false;

        if (absolutePath != null || basePath != null)
        {

            if (recurses > 0)
            {
                try
                {
                    String pathSplit[] = basePath.split("\\\\");
                    Object[] psplit = Tools.truncateArray(pathSplit, 1, true);
                    for (Object o : psplit)
                    {
                        internalPath += o + "\\";
                    }
                    //entfernt das letze element des pfades
                    //BSP: C:\pfad\zu\krempel\killme  -> C:\pfad\zu\krempel
                    //Kilme wird entfernt
                    
                    String replaceTemp = "";
                    for (int i = 0; i < recurses; i++)//recurses gibt an wievile ebenen er rauf ist
                    {
                        replaceTemp += "\\.\\.\\\\"; //  ..\ so oft wie der parser den baum raufgewandert ist
                    }
                    replace = "\\.\\\\" + replaceTemp; //beginnt pfad mit .\ und dann soviele ..\-s wie nötig
                    unRegex = internalPath.replaceAll("\\\\", "\\\\\\\\"); // \ -> \\
                    Tools.DebugHelperPrint("Aha", true, "Toolkit.enableFinerDebug");
                }
                catch (Exception ex)
                {
                    err = true;
                    Tools.DebugHelperPrint("FickDich", true, "Toolkit.enableFinerDebug");
                }


            }
            else
            {
                internalPath = basePath;
                replace = "\\.\\\\";
                unRegex = basePath.replaceAll("\\\\", "\\\\\\\\"); // \ -> \\
            }

            parsedPath = absolutePath.replaceAll(unRegex, replace);// basePath -> .\ haut den gemeinsamen teil raus und fügt den relativteil an
            Tools.DebugHelperPrint(parsedPath, true, "Toolkit.enableFinerDebug");
            if (parsedPath.equals(absolutePath))
            {
                //basePath=internalPath;
                recurses++;
                String parsedPath2 = null;
                //absolutePath = absolutePath.replaceAll("\\\\", "\\\\\\\\");
                try
                {
                    parsedPath2 = getRelativePath(absolutePath, internalPath, recurses);
                }
                catch (Exception ex)
                {
                    Tools.DebugHelperPrint("Arschfotze", true, "Toolkit.enableFinerDebug");
                }
                if (parsedPath2 != null)
                {
                    parsedPath = parsedPath2;
                }
            }
        }
        else
        {
            err = false;
        }
        if (err == true)
        {
            parsedPath = null;
        }
        return parsedPath;
    }
    /**
     * Fatei kopieren
     * Code ist ausm netz: http://www.javabeginners.de/Dateien_und_Verzeichnisse/Eine_Datei_kopieren.php
     * @param in Eingabefile
     * @param out Ausgabefile
     * @throws IOException 
     */
    
    public static void kopierpaste(File in, File out) //throws IOException
    {
        FileChannel inChannel=null,outChannel=null;
        try
        {
        inChannel = new FileInputStream(in).getChannel();
        outChannel = new FileOutputStream(out).getChannel();



            inChannel.transferTo(0, inChannel.size(), outChannel);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            System.err.println("Kopiererei geerrort");
          //  throw e;
        }
        finally
        {
            if (inChannel != null)
            {
                try
                {
                    inChannel.close();
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
            if (outChannel != null)
            {
                try
                {
                    outChannel.close();
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
        
    /**
     * Checkt ob pfad nen verzeichnis sit
     * @param path welcher pfad
     * @return ja/nein
     */
    public static boolean isDir(String path)
    {
        return new File(path).isDirectory();
    }
}
