package com.graphhopper.matching.cli;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.graphhopper.GraphHopper;
import com.graphhopper.PathWrapper;
import com.graphhopper.gpx.Gpx;
import com.graphhopper.matching.MapMatching;
import com.graphhopper.matching.MatchResult;
import com.graphhopper.reader.osm.GraphHopperOSM;
import com.graphhopper.routing.AlgorithmOptions;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.util.HintsMap;
import com.graphhopper.routing.weighting.FastestWeighting;
import com.graphhopper.util.*;
import io.dropwizard.cli.Command;
import io.dropwizard.setup.Bootstrap;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Collections;
import java.util.List;

public class MatchCommand extends Command {

    public MatchCommand() {
        super("match", "map-match one or more gpx files");
    }

    @Override
    public void configure(Subparser subparser) {
        subparser.addArgument("gpx")
                .type(File.class)
                .required(true)
                .nargs("+")
                .help("GPX file");
        subparser.addArgument("--instructions")
                .type(String.class)
                .required(false)
                .setDefault("")
                .help("Locale for instructions");
        subparser.addArgument("--max_visited_nodes")
                .type(Integer.class)
                .required(false)
                .setDefault(1000);
        subparser.addArgument("--gps_accuracy")
                .type(Integer.class)
                .required(false)
                .setDefault(40);
        subparser.addArgument("--transition_probability_beta")
                .type(Double.class)
                .required(false)
                .setDefault(2.0);
    }

    @Override
    public void run(Bootstrap bootstrap, Namespace args) {
        CmdArgs graphHopperConfiguration = new CmdArgs();
        graphHopperConfiguration.put("graph.location", "graph-cache");
        GraphHopper hopper = new GraphHopperOSM().init(graphHopperConfiguration);
        hopper.getCHFactoryDecorator().setEnabled(false);
        System.out.println("loading graph from cache");
        hopper.load(graphHopperConfiguration.get("graph.location", "graph-cache"));

        FlagEncoder firstEncoder = hopper.getEncodingManager().fetchEdgeEncoders().get(0);
        AlgorithmOptions opts = AlgorithmOptions.start().
                algorithm(Parameters.Algorithms.DIJKSTRA_BI).traversalMode(hopper.getTraversalMode()).
                weighting(new FastestWeighting(firstEncoder)).
                maxVisitedNodes(args.getInt("max_visited_nodes")).
                // Penalizing inner-link U-turns only works with fastest weighting, since
                // shortest weighting does not apply penalties to unfavored virtual edges.
                hints(new HintsMap().put("weighting", "fastest").put("vehicle", firstEncoder.toString())).
                build();
        MapMatching mapMatching = new MapMatching(hopper, opts);
        mapMatching.setTransitionProbabilityBeta(args.getDouble("transition_probability_beta"));
        mapMatching.setMeasurementErrorSigma(args.getInt("gps_accuracy"));

        StopWatch importSW = new StopWatch();
        StopWatch matchSW = new StopWatch();

        Translation tr = new TranslationMap().doImport().get(args.getString("instructions"));
        XmlMapper xmlMapper = new XmlMapper();

        for (File gpxFile : args.<File>getList("gpx")) {
            try {
                importSW.start();
                Gpx gpx = xmlMapper.readValue(gpxFile, Gpx.class);
                List<GPXEntry> inputGPXEntries = gpx.trk.getEntries();
                importSW.stop();
                matchSW.start();
                MatchResult mr = mapMatching.doWork(inputGPXEntries);
                matchSW.stop();
                System.out.println(gpxFile);
                System.out.println("\tmatches:\t" + mr.getEdgeMatches().size() + ", gps entries:" + inputGPXEntries.size());
                System.out.println("\tgpx length:\t" + (float) mr.getGpxEntriesLength() + " vs " + (float) mr.getMatchLength());
                System.out.println("\tgpx time:\t" + mr.getGpxEntriesMillis() / 1000f + " vs " + mr.getMatchMillis() / 1000f);

                String outFile = gpxFile.getAbsolutePath() + ".res.gpx";
                System.out.println("\texport results to:" + outFile);

                InstructionList il;
                if (args.getString("instructions").isEmpty()) {
                    il = new InstructionList(null);
                } else {
                    PathWrapper matchGHRsp = new PathWrapper();
                    new PathMerger().doWork(matchGHRsp, Collections.singletonList(mr.getMergedPath()), tr);
                    il = matchGHRsp.getInstructions();
                }
                try (BufferedWriter writer = new BufferedWriter(new FileWriter(outFile))) {
                    writer.append(il.createGPX("", 0, true, true, true, true, Constants.VERSION));
                }
            } catch (Exception ex) {
                importSW.stop();
                matchSW.stop();
                System.err.println("Problem with file " + gpxFile);
                ex.printStackTrace(System.err);
            }
        }
        System.out.println("gps import took:" + importSW.getSeconds() + "s, match took: " + matchSW.getSeconds());
    }

}

@@ -3486,16 +3486,45 @@
 rt().get
+WithFallBack(Helper.getLocale
 (args.ge
@@ -3547,16 +3547,94 @@
 tions%22))
+);%0A        final boolean withRoute = !args.getString(%22instructions%22).isEmpty()
 ;%0A      
@@ -4681,211 +4681,31 @@
     
-InstructionList il;%0A                if (args.getString(%22instructions%22).isEmpty()) %7B%0A                    il = new InstructionList(null);%0A                %7D else %7B%0A                    PathWrapper matchGHRsp
+PathWrapper pathWrapper
  = n
@@ -4718,28 +4718,24 @@
 hWrapper();%0A
-    
             
@@ -4762,26 +4762,27 @@
 .doWork(
-matchGHRsp
+pathWrapper
 , Collec
@@ -4831,81 +4831,8 @@
 r);%0A
-                    il = matchGHRsp.getInstructions();%0A                %7D%0A
     
@@ -4953,18 +4953,45 @@
 .append(
-il
+pathWrapper.getInstructions()
 .createG
@@ -4998,35 +4998,40 @@
 PX(%22%22, 0, true, 
-tru
+withRout
 e, true, true, C

Use same XML serialization in cli as in web service