#!/usr/bin/env python3

from lxml import etree
from math import ceil
from subprocess import Popen
import requests
import shutil
import os


def get_properties(url):
    ''' Returns number of tiles on each axis '''

    url = url.replace('.htm', '/ImageProperties.xml')
    r = requests.get(url)

    # Parse that xml
    try:
        root = etree.fromstring(r.text)
    except:
        return 0, 0

    width = int(root.get('WIDTH'))
    height = int(root.get('HEIGHT'))
    tile_size = int(root.get('TILESIZE'))

    horizontal_nb_tile = ceil(width / tile_size)
    vertical_nb_tile = ceil(height/ tile_size)

    return horizontal_nb_tile, vertical_nb_tile


def download_tiles(url, tiles, name):
    url = url.replace('.htm', '/TileGroup0')
    images = []
    for tile in tiles:
        code = 404
        level = 4
        while code == 404:
            r = requests.get("{}/{}-{}-{}.jpg".format(url, 
                                                      level,
                                                      tile[0],
                                                      tile[1]), 
                             stream=True)
            code = r.status_code
            level -= 1

        path = './images/{}/{}-{}.jpg'.format(name, tile[1], tile[0])
        with open(path, "wb") as img:
            shutil.copyfileobj(r.raw, img)
        del r

        images.append(path)
    return images


def download_map(url):
    name = url.split("/")[-1].split('.htm')[0]
    os.makedirs('images', exist_ok=True)
    os.makedirs('images/{}'.format(name), exist_ok=True)

    h_nb, v_nb = get_properties(url)
    if not h_nb or not v_nb:
        return

    tiles = [[ (x, y) for x in range(h_nb)] for y in range(v_nb) ]
    tiles = [item for sublist in tiles for item in sublist]

    images = download_tiles(url, tiles, name)
    montage(v_nb, name)


def montage(height, name):
    cmd = ["montage", "./images/{}/*".format(name), "-geometry +0+0", 
           "-tile x{}".format(height), "{}.jpg".format(name)]
    Popen(' '.join(cmd), shell=True)
    print("Map saved to '{}.jpg'".format(name))


def download_all(index_url):
    r = requests.get(index_url)
    html = etree.HTML(r.text)
    table = html.xpath("//table[@id = 'AutoNumber1']")[0]

    urls = []
    for tr in table.iterchildren():
        tds = list(tr.iterchildren())
        if tds:
            # contains URL
            urls_list = tds[0].findall('a')
            if urls_list:
                url = urls_list[0].get("href")
            else:
                continue

            if "http" in url:
                continue
            
            urls.append(url)

    for url in urls:
        download_map("{}/{}".format(index_url, url))


if __name__ == "__main__":
    download_all("http://exploration.urban.free.fr/minimal/")
