package org.artisanlogiciel.osm.convert;

import org.artisanlogiciel.graphics.Drawing;
import org.artisanlogiciel.graphics.DrawingLine;
import org.artisanlogiciel.osm.Node;
import org.artisanlogiciel.osm.NodeRef;
import org.artisanlogiciel.osm.OsmReader;
import org.artisanlogiciel.osm.Way;

import java.awt.*;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * Take a way with resolved ref ( ie with NodeRef having non null getNode() )
 * and create a Drawing from it.
 *
 * longitude will be x axis
 * latitude will be y axis
 *
 */
public class OsmToDrawing {

    double refx = 0;
    double refy = 0;
    int mulx = 1;
    int muly = 1;

    double minlat = 0;
    double minlon = 0;
    double maxlat = 180;
    double maxlon = 180;

    int boundserror = 0;

    public OsmToDrawing(OsmReader reader, int mulx, int muly)
    {
        this.refx = reader.getMinlat();
        this.minlat = reader.getMinlat();
        this.refy = reader.getMinlon();
        this.minlon = reader.getMinlon();
        this.maxlat = reader.getMaxlat();
        this.maxlon = reader.getMaxlon();
        this.mulx = mulx;
        this.muly = muly;

        System.out.println("minlat " + minlat);
        System.out.println("maxlat " + maxlat);
        System.out.println("minlon " + minlon);
        System.out.println("maxlon " + maxlon);
    }

    public OsmToDrawing(int mulx, int muly) {
        this.mulx = mulx;
        this.muly = muly;
    }

    public OsmToDrawing(double refx, double refy, int mulx, int muly) {
        this.refx = refx;
        this.refy = refy;
        this.mulx = mulx;
        this.muly = muly;
    }

    public DrawingLine getDrawingLine(Way way)
    {
        DrawingLine drawingLine = new DrawingLine();
        for (NodeRef nr : way.getNdlist())
        {
            Node node = nr.getNode();
            double lat = node.getLat();
            double lon = node.getLon();
            if (lat < minlat)
            {
                boundserror ++;
                System.err.println("lat < minlat " + lat );
            }
            else if (lat > maxlat)
            {
                boundserror ++;
                System.err.println("lat > minlat " + lat);
            }
            if (lon < minlon)
            {
                boundserror ++;
                System.err.println("lon < minlon " + lon);
            }
            else if (lon > maxlon)
            {
                boundserror ++;
                System.err.println("lon > minlon " + lon);
            }
            drawingLine.addPoint(new Point((int) ( (lon - refy ) * muly), (int) ( (lat - refx)* mulx ) ));
        }
        return drawingLine;
    }

    public Drawing getDrawing(List<Way> ways)
    {
        Drawing drawing = new Drawing();
        for (Way way : ways) {
            int currenterrors = boundserror;
            DrawingLine line = getDrawingLine(way);
            if ( currenterrors == boundserror ) {
                drawing.addLine(line);
            }
            else
            {
                System.err.println("skipping one line out of bound nodes");
            }
        }
        return drawing;
    }

    public static void main(String pArgs[])
    {
        if ( pArgs.length > 0 ) {
            String sample = pArgs[0];
            OsmReader osmreader = new OsmReader(sample);
            osmreader.read();
            osmreader.dump();
            OsmToDrawing converter = new OsmToDrawing(osmreader, 25000,25000);
            Drawing drawing = converter.getDrawing(osmreader.getWays());
            String savename = sample + ".ways";
            saveImc(savename, drawing);
            saveDrawing(savename, drawing);
            Drawing drawing2 = converter.getDrawing(osmreader.getBuildings());
            savename = sample + ".buildings";
            saveImc(savename, drawing2);
            saveDrawing(savename, drawing2);
        }
    }

    private static void saveDrawing(String sample, Drawing drawing) {
        try {
            FileOutputStream out = new FileOutputStream(sample + ".drawing");
            drawing.saveLines(new DataOutputStream(out));
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void saveImc(String sample, Drawing drawing) {
        try {
            FileOutputStream out = new FileOutputStream(sample + ".imc");
            drawing.saveLinesKompressed(new DataOutputStream(out));
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
