/FileExtraction/Java_unseen/PowerExplorer_PowerFileExplorer/PowerFileExplorer/src/main/java/chm/cblink/nb/chmreader/lib/Utils.java
package chm.cblink.nb.chmreader.lib;

import android.support.annotation.RequiresPermission;
import android.util.Log;

import org.ccil.cowan.tagsoup.jaxp.SAXParserImpl;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

/**
 * Created by nguyenbinh on 29/11/2016.
 */

public class Utils {
    public static CHMFile chm = null;

    public static ArrayList<String> domparse(String filePath, String extractPath, String md5) throws IOException {
        final ArrayList<String> listSite = new ArrayList<>();
        listSite.add(md5);
//        Document doc = Jsoup.parse(chm.getResourceAsStream(""), "UTF-8", "");
//        Elements listObject = doc.getElementsByTag("object");
//        for (Element object : listObject) {
//            Elements listParam = object.getElementsByTag("param");
//            if (listParam.size() > 0) {
//                String name = "", local = "";
//                for (Element param : listParam) {
//                    if (param.attributes().getIgnoreCase("name").equalsIgnoreCase("name")) {
//                        name = param.attributes().getIgnoreCase("value");
//                    } else if (param.attributes().getIgnoreCase("name").equalsIgnoreCase("local")) {
//                        local = param.attributes().getIgnoreCase("value");
//                    }
//                }
//                listSite.add(local);
//                object.parent().prepend("<a href=\"" + local + "\">" + name + "</a>");
//                object.remove();
//            }
//        }
//        try {
//            FileOutputStream fosHTMLMap =  new FileOutputStream(extractPath + "/" +md5);
//            fosHTMLMap.write(doc.outerHtml().getBytes());
//            fosHTMLMap.close();
//
//            FileOutputStream fosListSite =  new FileOutputStream(extractPath + "/site_map_" +md5);
//            for(String str: listSite) {
//                fosListSite.write((str+";").getBytes());
//            }
//            fosListSite.close();
//            Log.e("Utils", "write ok " + "/site_map_" +md5);
//        } catch (IOException e) {
//            e.printStackTrace();
//            Log.e("Utils", "write ok sitemap error");
//        }
        ///////////////////////////////////////////////////
        try {

            final FileOutputStream fosHTMLMap = new FileOutputStream(extractPath + "/" + md5);
            final FileOutputStream fosListSite = new FileOutputStream(extractPath + "/site_map_" + md5);
            try {
                fosListSite.write((md5 + ";").getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(chm.getResourceAsStream("") != null) {
                SAXParserImpl.newInstance(null).parse(
                        chm.getResourceAsStream(""),
                        new DefaultHandler() {
                            class MyUrl {
                                public int status = 0;
                                public String name;
                                public String local;

                                public String toString() {
                                    if (status == 1)
                                        return "<a href=\"#\">" + name + "</a>";
                                    else
                                        return "<a href=\"" + local + "\">" + name + "</a>";
                                }
                            }

                            MyUrl url = new MyUrl();
                            HashMap<String, String> myMap = new HashMap<String, String>();
                            int count = 0;

                            public void startElement(String uri, String localName, String qName,
                                                     Attributes attributes) throws SAXException {

                                if (qName.equals("param")) {
                                    count++;
                                    for (int i = 0; i < attributes.getLength(); i++) {
                                        myMap.put(attributes.getQName(i).toLowerCase(), attributes.getValue(i).toLowerCase());
                                    }
                                    if (myMap.get("name").equals("name") && myMap.get("value") != null) {
                                        url.name = myMap.get("value");
                                        url.status = 1;
                                    } else if (myMap.get("name").equals("local") && myMap.get("value") != null) {
                                        url.local = myMap.get("value");
                                        url.status = 2;
                                        listSite.add(url.local.replaceAll("%20", " "));
                                        try {
                                            fosListSite.write((url.local.replaceAll("%20", " ") + ";").getBytes());
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    }

                                    if (url.status == 2) {
                                        url.status = 0;
                                        try {
                                            fosHTMLMap.write(url.toString().getBytes());
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                } else {
                                    if (url.status == 1) {
                                        try {
                                            fosHTMLMap.write(url.toString().getBytes());
                                            url.status = 0;
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }

                                if (!qName.equals("object") && !qName.equals("param"))
                                    try {
                                        fosHTMLMap.write(("<" + qName + ">").getBytes());
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }


                            }

                            public void endElement(String uri, String localName,
                                                   String qName) throws SAXException {
                                if (!qName.equals("object") && !qName.equals("param"))
                                    try {
                                        fosHTMLMap.write(("</" + qName + ">").getBytes());
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                            }
                        }
                );
            }else{
                fosHTMLMap.write("<HTML> <BODY> <UL>".getBytes());
                for(String fileName: chm.list()){
                    fileName = fileName.substring(1);
                    if(fileName.endsWith(".htm")||fileName.endsWith(".html")){
                        fosListSite.write((fileName + ";").getBytes());
                        fosHTMLMap.write(("<li><a href=\""+fileName+"\">" + fileName + "</a></li>").getBytes());
                        listSite.add(fileName);
                    }
                }
                fosHTMLMap.write("</UL> </BODY> </HTML>".getBytes());
            }
            fosHTMLMap.close();
            fosListSite.close();
        } catch (SAXException | IOException e) {
            e.printStackTrace();
        }
        ///////////////////////////////////////////////////


        return listSite;
    }

    public static ArrayList<String> getListSite(String extractPath, String md5) {
        ArrayList<String> listSite = new ArrayList<>();

        StringBuilder reval = new StringBuilder();
        try {
            InputStream in = new FileInputStream(extractPath + "/site_map_" + md5);
            byte[] buf = new byte[1024];
            int c = 0;
            while ((c = in.read(buf)) >= 0) {
                reval.append(new String(buf, 0, c));
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        String[] arrSite = reval.toString().split(";");
        Collections.addAll(listSite, arrSite);
        return listSite;
    }

    public static ArrayList<String> getBookmark(String extractPath, String md5) {
        ArrayList<String> listBookMark = new ArrayList<>();
        StringBuilder reval = new StringBuilder();
        try {
            InputStream in = new FileInputStream(extractPath + "/bookmark_" + md5);
            byte[] buf = new byte[1024];
            int c = 0;
            while ((c = in.read(buf)) >= 0) {
                reval.append(new String(buf, 0, c));
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String[] arrSite = reval.toString().split(";");
        for (String str : arrSite) {
            if (str.length() > 0) {
                listBookMark.add(str);
            }
        }
        return listBookMark;
    }

    public static int getHistory(String extractPath, String md5) {
        StringBuilder reval = new StringBuilder();
        try {
            InputStream in = new FileInputStream(extractPath + "/history_" + md5);
            byte[] buf = new byte[1024];
            int c = 0;
            while ((c = in.read(buf)) >= 0) {
                reval.append(new String(buf, 0, c));
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            return 1;
        }
        try {
            return Integer.parseInt(reval.toString());
        }catch (Exception e){
            return 0;
        }

    }



    public static void saveBookmark(String extractPath, String md5, ArrayList<String> listBookmark) {
        try {
            FileOutputStream fos = new FileOutputStream(extractPath + "/bookmark_" + md5, false);
            for (String str : listBookmark) {
                fos.write((str + ";").getBytes());
            }
            fos.close();
        } catch (IOException ignored) {
        }
    }

    public static void saveHistory(String extractPath, String md5, int index) {
        try {
            FileOutputStream fos = new FileOutputStream(extractPath + "/history_" + md5, false);
            fos.write((""+index).getBytes());
            fos.close();
        } catch (IOException ignored) {
        }
    }


    private static String getSiteMap(String filePath) {
        StringBuilder reval = new StringBuilder();
        try {
            if (chm == null) {
                chm = new CHMFile(filePath);
            }
            byte[] buf = new byte[1024];
            InputStream in = chm.getResourceAsStream("");
            int c = 0;
            while ((c = in.read(buf)) >= 0) {
                reval.append(new String(buf, 0, c));
            }
//            chm.close();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
        return reval.toString();
    }

    public static boolean extract(String filePath, String pathExtract) {
        try {
            if (chm == null) {
                chm = new CHMFile(filePath);
            }
            File filePathTemp = new File(pathExtract);
            if (!filePathTemp.exists()) {
                if (!filePathTemp.mkdirs()) throw new IOException();
            }
//            for (String file : chm.list()) {
//                String temp = pathExtract + file;
//                String tempName = temp.substring(temp.lastIndexOf("/") + 1);
//                String tempPath = temp.substring(0, temp.lastIndexOf("/"));
//                File filePathTemp = new File(tempPath);
//                if (!filePathTemp.exists()) {
//                    if (!filePathTemp.mkdirs()) throw new IOException();
//                }
//                if (tempName.length() > 0) {
//                    FileOutputStream fos = null;
//                    try {
//                        fos = new FileOutputStream(temp);
//                        byte[] buf = new byte[1024];
//                        InputStream in = chm.getResourceAsStream(file);
//                        int c;
//                        while ((c = in.read(buf)) >= 0) {
//                            fos.write(buf, 0, c);
//                        }
//                    } catch (IOException e) {
//                        Log.d("Error extract file: ", file);
//                        e.printStackTrace();
//                    } finally {
//                        if (fos != null) fos.close();
//                    }
//                }
//            }
//            chm.close();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static String checkSum(String path) {
        String checksum = null;
        try {
            FileInputStream fis = new FileInputStream(path);
            MessageDigest md = MessageDigest.getInstance("MD5");

            //Using MessageDigest update() method to provide input
            byte[] buffer = new byte[8192];
            int numOfBytesRead;
            while ((numOfBytesRead = fis.read(buffer)) > 0) {
                md.update(buffer, 0, numOfBytesRead);
            }
            byte[] hash = md.digest();
            checksum = new BigInteger(1, hash).toString(16); //don't use this, truncates leading zero
        } catch (IOException ex) {
			ex.printStackTrace();
        } catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
        }
        return checksum.trim();
    }

    public static boolean extractSpecificFile(String filePath, String pathExtractFile, String insideFileName) {
        try {
            if (chm == null) {
                chm = new CHMFile(filePath);
            }
            if(new File(pathExtractFile).exists()) return true;
            String path = pathExtractFile.substring(0, pathExtractFile.lastIndexOf("/"));
            File filePathTemp = new File(path);
            if (!filePathTemp.exists()) {
                if (!filePathTemp.mkdirs()) throw new IOException();
            }
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(pathExtractFile);
                byte[] buf = new byte[1024];
                InputStream in = chm.getResourceAsStream(insideFileName);
                int c;
                while ((c = in.read(buf)) >= 0) {
                    fos.write(buf, 0, c);
                }
            } catch (IOException e) {
                Log.d("Error extract file: ", insideFileName);
                e.printStackTrace();
            } finally {
                if (fos != null) fos.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
