package kamiworldserver.control;

import java.util.logging.Level;
import java.util.logging.Logger;
import kamiworldserver.elem.KamiMap;

import java.io.*;

import java.net.URL;
import java.net.URLConnection;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import java.util.HashMap;

public class KamiWorldLoader extends Thread {

    String sHost = null;
    String[] sFiles = null;
    HashMap<String, KamiMap> hmMaps = null;
    DocumentBuilderFactory dbfFactory = null;
    DocumentBuilder dBuilder = null;
    StringBuilder sURL;
    String line;
    int len;
    URL url;
    URLConnection urlc;
    BufferedReader br;
    KamiMap km;

    public KamiWorldLoader() {
        dbfFactory = DocumentBuilderFactory.newInstance();
        dbfFactory.setIgnoringElementContentWhitespace(true);
        dbfFactory.setValidating(false);

        sURL = new StringBuilder(255);
        try {
            dBuilder = dbfFactory.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            ex.printStackTrace();
        }
    }

    public void loadToMap(String[] files, HashMap<String, KamiMap> hm) {

        hmMaps = hm;
        sFiles = files;

        if (sFiles == null || sFiles[0].length() < 1) {
            System.out.println("WARNING! No maps loaded.");
            return;
        }
        try {
            System.out.println("Maps count: " + sFiles.length + " - parsing.");

            sURL.append("http://");
            sURL.append(sHost);
            sURL.append("/");
            len = sURL.length();

            for (String f : sFiles) {
                sURL.replace(len, len + f.length(), f.replaceAll(" ", "%20"));
                f = f;
                hm.put(f, new KamiMap(f, dBuilder.parse(sURL.toString())));
                sURL.delete(len, len + f.length() + 1);
            }

        } catch (SAXException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    public void recheckFile(String s) {
        long l;
        try {
            km = hmMaps.get(s.toLowerCase());
            if (km == null) {
                loadMap(s);
                return;
            }

            sURL.delete(len, len + s.length() + 1);
            sURL.replace(len, len + s.length(), s.replaceAll(" ", "%20"));

            url = new URL(sURL.toString());
            urlc = url.openConnection();
            urlc.setUseCaches(false);
            br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));

            do {
                line = br.readLine();
                if (line != null && line.startsWith("<root")) {
                    l = line.indexOf('"') + 1;
                    l = Long.parseLong(line.substring((int) l, line.indexOf('"', ((int) l))));

                    if (!km.checkMod(l)) {
                        try {
                            br.close();
                            dBuilder.reset();
                            synchronized (km) {
                                //km.recreate(dBuilder.parse(s.toString()));
                                km.recreate(dBuilder.parse(url.openStream()));
                            }
                            System.out.println("Map recreated: " + s.toString());
                        } catch (SAXException ex) {
                            ex.printStackTrace();
                        }
                    }
                    break;
                }
            } while (line != null);

            sURL.delete(len, len + s.length() + 1);
            br.close();

        } catch (java.io.FileNotFoundException ex) {
            hmMaps.remove(km);
        } catch (IOException e) {
            System.out.println("[KamiWorldLoader::recheckFile] IOException.");
            //e.printStackTrace();
        }
    }
    
    public void loadMap(String s) {
        sURL.delete(len, len + s.length() + 1);
        sURL.replace(len, len + s.length(), s.replaceAll(" ", "%20"));
        try {
            hmMaps.put(s, new KamiMap(s, dBuilder.parse(sURL.toString())));
        } catch (SAXException ex) {
            System.out.println("[KamiWorldLoader::loadMap] SAXException.");
            //ex.printStackTrace();
        } catch (IOException ex) {
            System.out.println("[KamiWorldLoader::loadMap] IOException.");
            //ex.printStackTrace();
        }
        sURL.delete(len, len + s.length() + 1);
        System.out.println("Map loaded: " + s.toString());
    }

    /*
    @Override
    public void run() {
        if (sFiles == null || sFiles[0].length() < 1) {
            return;
        }

        StringBuilder s = new StringBuilder(255);
        s.append("http://");
        s.append(sHost);
        s.append("/");
        int len = s.length();

        long l;
        String f;
        String line;
        URL url;
        URLConnection urlc;
        BufferedReader br;
        KamiMap km = null;
        while (true) {
            try {
                f = sFiles[nCurrent];
                km = hmMaps.get(f.toLowerCase());
                s.delete(len, len + f.length() + 1);
                s.replace(len, len + f.length(), f.replaceAll(" ", "%20"));

                url = new URL(s.toString());
                urlc = url.openConnection();
                urlc.setUseCaches(false);
                br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));

                do {
                    line = br.readLine();
                    if (line != null && line.startsWith("<root")) {
                        l = line.indexOf('"') + 1;
                        l = Long.parseLong(line.substring((int) l, line.indexOf('"', ((int) l))));

                        if (!km.checkMod(l)) {
                            try {
                                br.close();
                                dBuilder.reset();
                                synchronized (km) {
                                    //km.recreate(dBuilder.parse(s.toString()));
                                    km.recreate(dBuilder.parse(url.openStream()));
                                }
                                System.out.println("Map recreated: " + s.toString());
                            } catch (SAXException ex) {
                                ex.printStackTrace();
                            }
                        }
                        break;
                    }
                } while (line != null);

                br.close();

                ++nCurrent;
                if (nCurrent >= sFiles.length) {
                    nCurrent = 0;
                    checkList();
                    System.gc();
                }

                Thread.sleep(1000);

            } catch (java.io.FileNotFoundException ex) {
                hmMaps.remove(km);
            } catch (InterruptedException ex) {
                Logger.getLogger(KamiWorldLoader.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException e) {
                System.out.println("World Loader unknow error.");
                e.printStackTrace();
                System.exit(-1);
            }
        }
    }
     */
/*
    private void checkList() {

        String[] files = getList(sHost);
        if (files.length <= sFiles.length) {
            return;
        }

        int i = 0;
        int off = 0;
        String tmp;
        StringBuilder s = new StringBuilder(255);
        s.append("http://");
        s.append(sHost);
        s.append("/");
        int len = s.length();


        while (i < sFiles.length) {
            if (sFiles[i].charAt(0) != files[i + off].charAt(0)) {
                s.delete(len, len + files[i + off].length() + 1);
                s.replace(len, len + files[i + off].length(), files[i + off].replaceAll(" ", "%20"));
                tmp = files[i + off].toLowerCase();
                synchronized (hmMaps) {
                    try {
                        hmMaps.put(tmp, new KamiMap(tmp, dBuilder.parse(s.toString())));
                    } catch (SAXException ex) {
                        Logger.getLogger(KamiWorldLoader.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IOException ex) {
                        Logger.getLogger(KamiWorldLoader.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                ++off;
                continue;
            }
            ++i;
        }

        sFiles = files;
    }
 */

    public String[] getList(String host) {

        sHost = host;

        try {
            URL uURL = new URL("http://" + host + "/listall.php");
            URLConnection ucConnection = uURL.openConnection();

            // sending POST data
            ucConnection.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(ucConnection.getOutputStream());
            wr.write(java.net.URLEncoder.encode("type", "UTF-8") + "=" + java.net.URLEncoder.encode("server", "UTF-8"));
            wr.flush();
            wr.close();

            // getting results
            BufferedReader br = new BufferedReader(new InputStreamReader(ucConnection.getInputStream()));

            StringBuilder sDoc = new StringBuilder();
            String sLine;
            while ((sLine = br.readLine()) != null) {
                sDoc.append(sLine);
                if (sLine.contains("#end#")) {
                    break;
                }
            }

            String s = sDoc.substring(sDoc.indexOf("list=") + 5, sDoc.indexOf("#end#"));

            return s.split(";");


        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            System.out.println("Unable to load maps listing.");
        }

        return null;

    }
}
