package de.daggit.domap.stitch

import groovy.util.logging.Log
import org.apache.commons.io.FileUtils

import javax.imageio.ImageIO
import java.awt.Graphics2D
import java.awt.image.BufferedImage

/**
 * Created by jbialek on 13.07.16.
 */
@Log
class Stitcher {

    double ppm = 10 // Pixel Per Meter
    double x
    double y
    String base
    int tilePixelWidth = 2048
    int tilePixelHeight = 2048
    String tmpDir

    double getTileWidth() {
        return tilePixelWidth/ppm
    }

    double getTileHeight() {
        return tilePixelHeight/ppm
    }

    Stitcher(String base, double x, double y) {
        this.base = base
        this.x = x
        this.y = y
        this.tmpDir = System.currentTimeMillis() as String
    }

    BufferedImage load() {
        List<Tile> firstRow = []
        List<Tile> firstColumn = []
        Tile tile = null
        while ((tile==null)||!tile.isLastX()) {
            tile = load(firstRow.size(), 0)
            firstRow << tile
        }
        tile = firstRow[0]
        firstColumn << tile
        while ((tile==null)||!tile.isLastY()) {
            tile = load(0, firstColumn.size())
            firstColumn << tile
        }

        BufferedImage img = new BufferedImage(tilePixelWidth * firstRow.size(), tilePixelHeight * firstColumn.size(), BufferedImage.TYPE_INT_ARGB)
        Graphics2D g = img.createGraphics()
        firstRow.eachWithIndex { Tile entry, int i ->
            g.drawImage(entry.image, i * tilePixelWidth, 0, null)
        }
        firstColumn.eachWithIndex { Tile entry, int i ->
            g.drawImage(entry.image, 0, i * tilePixelHeight, null)
        }
        int max = firstRow.size() * firstColumn.size()
        int cnt = firstRow.size() + firstColumn.size() -1
        for (int u=1; u<firstRow.size(); u++) {
            for (int v=1; v<firstColumn.size(); v++) {
                Tile t = load(u, v)
                g.drawImage(t.image, u * tilePixelWidth, v * tilePixelHeight, null)
                printProgress(u, v, max, cnt)
                cnt++
            }
        }
        g.dispose()
        new File(tmpDir).deleteDir()
        return img
    }

    def printProgress(int u, int v, int max, int cnt) {
        print("\r[")
        int w = 25
        for (int i=0; i<w; i++) {
            if (((double)w / max * cnt) > i) {
                print("#")
            } else {
                print("-")
            }
        }
        double percent = Math.round(100d/max*cnt)
        print("] $percent%")
    }

    Tile load(int u, int v) {
        Tile tile = new Tile(u: u, v: v)
        tile.tmpDir = tmpDir
        tile.x1 = this.x + u * tileWidth
        tile.y1 = this.y + -v * tileHeight
        tile.x2 = this.x + (u+1) * tileWidth
        tile.y2 = this.y + (-v+1) * tileHeight
        URL url = new URL("${base}${tile}&WIDTH=$tilePixelWidth&HEIGHT=$tilePixelHeight")
        //log.info("Tile $u/$v -> $url")
        int retryCount = 3
        for(;;) {
            try {
                File file = new File("$tmpDir/tile${u},${v}.gif")
                if (!file.parentFile.exists()) {
                    file.parentFile.mkdirs();
                }

                FileUtils.copyURLToFile(url, file)
                log.info("Saved $url to ${file.absolutePath} (Size: ${file?.size()}")
                tile.imageFile = file
                break
            } catch (IOException ioe) {
                retryCount--
                if (!retryCount) {
                    throw ioe
                }
                log.warning("${ioe.class.simpleName}: ${ioe.message}, Retrying...")
            }
        }
        return tile
    }

    static void main(def args) {
        println "Supported image formats: ${ImageIO.readerFormatNames.join(", ")}"
        System.properties."http.proxyHost" = "172.16.136.10"
        System.properties."http.proxyPort" = "8181"
        System.properties."https.proxyHost" = "172.16.136.10"
        System.properties."https.proxyPort" = "8181"
        HttpURLConnection.setFollowRedirects(true)

        //http://geoweb1.digistadtdo.de:80/OWSServiceProxy/bplan.sws?SEC_DATA=//fsgeop01/doris/Doris/BPLAN/Mengede/Mg131ooo01.map&LAYERS=Bebauungsplan&STYLES=&HEIGHT=520&WIDTH=923&SRS=EPSG%3A31466&FORMAT=image%2Fgif&TRANSPARENT=true&FEATUREINFO=true&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=2596042.5177248,5715999.2721278,2596530.9382944,5716274.4386458
        BufferedImage b1 = new Stitcher("https://geoweb1.digistadtdo.de/OWSServiceProxy/bplan.sws?SEC_DATA=//fsgeop01/doris/Doris/BPLAN/Mengede/Mg131ooo01.map&LAYERS=Bebauungsplan&STYLES=&SRS=EPSG%3A31466&FORMAT=image%2Fgif&TRANSPARENT=true&FEATUREINFO=true&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=",
                2596042.5177248,5715999.2721278
        ).load()
        ImageIO.write(b1, "gif", new File("b1.gif"))
        BufferedImage b2 = new Stitcher("https://geoweb1.digistadtdo.de/OWSServiceProxy/bplan.sws?SEC_DATA=//fsgeop01/doris/Doris/BPLAN/Mengede/Mg131ooo02.map&LAYERS=Bebauungsplan&STYLES=&SRS=EPSG%3A31466&FORMAT=image%2Fgif&TRANSPARENT=true&FEATUREINFO=true&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=",
                2596056.0014041,5715363.062297
        ).load()
        ImageIO.write(b2, "gif", new File("b2.gif"))

    }

}
