
import java.io.File;
import java.util.*;

import org.jdom2.Document;
import org.jdom2.Element;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.jdom2.input.SAXBuilder;


public class BusStopParser extends DefaultHandler {

    private HashMap<String,Integer> counts = new HashMap<String, Integer>();

    /*public void countElements(Element e){
        String name = e.getName();

        if(counts.containsKey(name)){
            counts.put(name,counts.get(name)+1);
        } else {
            counts.put(name,1);
        }

        List<Element> elems = e.getChildren();
        for(int i=0;i<elems.size();i++){
            countElements(elems.get(i));
        }
    }
    public void main(String[] args) {
        System.out.println("Hello world!");

        File configFile = new File( "./imports/bme.xml");

        if (configFile.exists()) {
            try {
                SAXBuilder saxBuilder = new SAXBuilder();
                Document document = saxBuilder.build(configFile);

                Element rootElement = document.getRootElement();

                countElements(rootElement);

                printMap();

            } catch (Exception e) {
                System.err.println("Error reading the file: " + e.getMessage());
                e.printStackTrace();
            }
        } else {
            System.out.println("File does not exist: config.xml");
        }
    }*/

    public void printMap(){
        for(String key: counts.keySet()){
            System.out.println(key+" : " +counts.get(key)+"\n---");
        }
    }

    private enum Phase {
        LOOK_FOR_OPENER_TAG,
        OPENER_NODE_FOUND,
        LOOK_FOR_CLOSE_TAG
    }

    Phase innerPhase = Phase.LOOK_FOR_OPENER_TAG;

    private String nameAttr = "";
    private String oldNameVAttr = "";
    private String wheelChairAttr = "";
    private int foundAttributes = 0;
    private boolean isValid = false;

    private double curLon = 0.0;
    private double curLat = 0.0;

    double dist1(double lat1, double lon1, double lat2, double lon2) {
        double R = 6371000; // metres
        double phi1 = Math.toRadians(lat1);
        double phi2 = Math.toRadians(lat2);
        double dphi = phi2-phi1;
        double dl = Math.toRadians(lon2-lon1);

        double a = Math.sin(dphi/2) * Math.sin(dphi/2) +
                Math.cos(phi1) * Math.cos(phi2) *
                        Math.sin(dl/2) * Math.sin(dl/2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        double d = R * c;
        return d;
    }

    private List<BusStop> busStops = new ArrayList<>();

    public void printBusStops(){
        for(BusStop b: busStops){
            b.print();
        }
    }


    public void printBusStopsByDistance(double lat, double lon){
        for(int i=0;i<busStops.size();i++){
            busStops.get(i).setDistance(dist1(lat,lon,busStops.get(i).getLat(),busStops.get(i).getLon()));
        }

        Collections.sort(busStops, new Comparator<BusStop>() {
            public int compare(BusStop s1, BusStop s2) {
                return Double.compare(s1.getDistance(),s2.getDistance());
            }
        });

        for(BusStop b: busStops){
            b.printByDistance();
        }
    }

    @Override
    public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException {
        switch (innerPhase){
            case LOOK_FOR_OPENER_TAG:
                if(qName.equals("node")){
                    foundAttributes=0;
                    innerPhase=Phase.OPENER_NODE_FOUND;
                    isValid = false;

                    curLon = Double.parseDouble(attributes.getValue("lon"));
                    curLat = Double.parseDouble(attributes.getValue("lat"));
                }
                break;
            case OPENER_NODE_FOUND:
                String k = attributes.getValue("k");
                String v = attributes.getValue("v");
                if(k != null && v != null){
                    switch(k){
                        case "highway":
                            if (v.equals("bus_stop")){
                                isValid=true;
                            }
                            break;
                        case "name":
                            nameAttr= v;
                            foundAttributes++;
                            break;
                        case "old_name":
                            oldNameVAttr= v;
                            foundAttributes++;
                            break;
                        case "wheelchair":
                            wheelChairAttr= v;
                            foundAttributes++;
                            break;
                    }
                }
                if(foundAttributes==3){
                    innerPhase=Phase.LOOK_FOR_CLOSE_TAG;
                    if(isValid == true){
                        BusStop curBus = new BusStop(nameAttr,oldNameVAttr,wheelChairAttr);
                        curBus.setLat(curLat);
                        curBus.setLon(curLon);
                        busStops.add(curBus);

                    }

                }

                break;
        }
    }

    @Override
    public void endElement (String uri, String localName, String qName) throws SAXException {
        if(qName.equals("node") && innerPhase == Phase.LOOK_FOR_CLOSE_TAG){
            innerPhase=Phase.LOOK_FOR_OPENER_TAG;
        }
    }
}