#!/usr/bin/env python3
import sys
import os
import re
import json
import requests
import urllib.request
import tarfile
import hashlib

home = os.path.expanduser("~")
steam = 'steamapps/compatdata/284160/pfx/drive_c/users/steamuser'
game = '/AppData/Local/BeamNG.drive/'

custom = False

tags = []
hash_table = []
#Names of default maps in the GitHub repo
default = ['etk', 'jri', 'utah', 'derby', 'hirochi', 'industrial', 'gridmap_v2', 'small_island', 'east_coast_usa', 'wcusa', 'italy',]

try:
    path = str(sys.argv[1])
    custom = True
except:
    path = home + '/.steam/root/' + steam + game
    if not os.path.exists(path): #Flatpak?
        path = home + '/.var/app/com.valvesoftware.Steam/.steam/root/' + steam + game
        if not os.path.exists(path): #Wine?
            path = home + '/.wine/drive_c/users/' + os.getlogin() + game

#The path did not exist
if not os.path.exists(path):
    print('\nWas looking for:')
    if not custom:
        print(' 1. STEAM .deb\n 2. STEAM flatpak\n 3. WINE  "' + path + '"\nbut found nothing.')
        print('\nTry adding the equivalent of %LOCALAPPDATA%\LOCAL\BEAMNG.DRIVE as a parameter\n or try the troubleshooting section of the guide.')
    else:
        print(' "' + path + '"\nbut found nothing.')
        print('Verify that your path leads to %LOCALAPPDATA%\LOCAL\BEAMNG.DRIVE')
    print('\n')
    quit()

#Get the current version to find the correct folder (I can see this breaking - would be better to use latest.lnk)
with open(path + 'version.txt') as version_file:
  ver = version_file.read().split('.')
version = ver[0] + '.' + ver[1] + '/'

#Path of mods folder
mods = path + version + 'mods/'

#Path to extract the cache to
cache = path + version + 'temp/art/'

#Create folders if missing
if not os.path.exists(cache + '/terrainMaterialCache'):
    os.makedirs(cache + '/terrainMaterialCache')

#Get installed mods
with open(mods + 'db.json') as file:
    repodb = json.load(file)

#Get supported maps from GitHub
response = requests.get('https://api.github.com/repos/snoutbug/beamng_terrainmaterialcache/tags').json()

#tag = mod_id
for tag in response:
    tags.append(str(tag['name']))

print('\n\nStarting to update.\nYou can always cancel the download by pressing CTRL + C')
print('\nLooking for modded maps...')

#Generate Hashes for existing .dds
def md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

for dds in os.listdir(cache + 'terrainMaterialCache/'):
    hash_table.append(md5(cache + 'terrainMaterialCache/' + dds) + '  ' + dds)

#If a used mod is supported by the repo, then only download the textures when there is at least one
#   texture missing or changed
try:
    for mod in repodb['mods']:
        try:
            mod_id = str(repodb['mods'][mod]['modData'].get('resource_id'))
            mod_title = str(repodb['mods'][mod]['modData'].get('title'))
        except:
            continue
        if mod_id in tags:
            print('Verifying ' + mod_title)
            hash_url = 'https://github.com/SnoutBug/BeamNG_terrainMaterialCache/releases/download/' + mod_id + '/md5.txt'
            hash_filename = mod_id + '_md5.txt'
            urllib.request.urlretrieve(hash_url, hash_filename)
            with open(hash_filename) as hash_file:
                hashes = hash_file.read().splitlines()
            os.remove(hash_filename)
            for hash in hashes:
                if not hash in hash_table:
                    print('  > Downloading Files...')
                    url = 'https://github.com/SnoutBug/BeamNG_terrainMaterialCache/releases/download/' + mod_id + '/main.tar.gz'
                    filename = mod_id + '.tar.gz'
                    urllib.request.urlretrieve(url, filename)
                    with tarfile.open(filename) as tar:
                        tar.extractall(cache)
                    os.remove(filename)
                    break #continue with next mod

    #Same as mods but with different naming conventions
    print('\nLooking for default maps...')
    url = 'https://github.com/SnoutBug/BeamNG_terrainMaterialCache/releases/download/default/'
    for filename in default:
        print('Verifying ' + filename)
        hash_url = url + filename + '_md5.txt'
        hash_filename = filename + '_md5.txt'
        urllib.request.urlretrieve(hash_url, hash_filename)
        filename = filename + '.tar.gz'
        with open(hash_filename) as hash_file:
            hashes = hash_file.read().splitlines()
        os.remove(hash_filename)
        for hash in hashes:
            if not hash in hash_table:
                print('  > Downloading Files...')
                urllib.request.urlretrieve(url + filename, filename)
                with tarfile.open(filename) as tar:
                    tar.extractall(cache)
                os.remove(filename)
                break #continue with next map

    print('All Done!')

#Remove all partially downloaded files when cancelled
except KeyboardInterrupt:
    try:
        os.remove(filename)
    except OSError:
        pass
    try:
        os.remove(hash_filename)
    except OSError:
        pass
    print('\nYou cancelled the download.')

quit()