#!/usr/bin/env python

import os
import argparse
import socket
import time
import hashlib
import shutil

import subprocess
import logging

def run_stage(q3map2_path, game_path, map_path, stage):
    logging.info("Running BSP stage: {}".format(map_path))
    map_root, map_extension = os.path.splitext(map_path)
    bsp_path = map_root + ".bsp"
    match stage:
        case 0:
            cmd = ["wine {0} "
            "-v "
            "-game qfusion "
            "-custinfoparms "
            "-threads 8 "
            "-fs_basepath {1} "
            "-fs_game mguns "
            "-samplesize 16 "
            "-meta "
            "{2} "
            "{3}"
            .format(q3map2_path, game_path, map_path, bsp_path)]
        case 1:
            cmd = ["wine {0} "
            "-v "
            "-vis "
            "-game qfusion "
            "-custinfoparms "
            "-threads 8 "
            "-fs_basepath {1} "
            "-fs_game mguns "
            "-saveprt "
            "{2} "
            "{3}"
            .format(q3map2_path, game_path, map_path, bsp_path)]
        case 2:
            cmd = ["wine {0} "
            "-v "
            "-game qfusion "
            "-fs_basepath {1} "
            "-fs_game mguns "
            "-light "
            "-meta "            
            "-dirty "
            "-dirtmode 0 "
            "-dirtscale 1.1 "
            "-threads 8 "
            "-custinfoparms "
            "-compensate 4 "
            "-style "
            "-fast "
            "-nocollapse "
            "{2} "
            "{3}"
            .format(q3map2_path, game_path, map_path, bsp_path)]            
    logging.info(cmd)
    subprocess.check_call(cmd, cwd=os.path.dirname(map_path), shell=True)

def md5(fname):
    logging.info(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()

def copy_bsp(bsp_path, dest_path):
    os.makedirs(dest_path, exist_ok=True)
    print(f"Copying '{bsp_path}' copied to '{dest_path}'")
    shutil.copy2(bsp_path, dest_path)
    

if ( __name__ == '__main__' ):
    parser = argparse.ArgumentParser()
    parser.add_argument( '--verbose', required = False, action = 'store_true', help = 'Be more verbose' )

    default_q3map2_path = '/home/jehar/media/dlab3/shares/Public/mguns/maps/q3map2/q3map2.exe'
    parser.add_argument( '--q3map2-path', required = False, action = 'store',
        default = default_q3map2_path,
        help = 'Path to q3map2 (default = {})'.format(default_q3map2_path)
    )

    default_game_path = '/home/jehar/gits/midnight-guns/'
    parser.add_argument( '--game-path', required = False, action = 'store',
        default = default_game_path,
        help = 'Base path for Midnight Guns folder (default = {})'.format(default_game_path)
    )

    parser.add_argument( '--map', required = True, action = 'store',
        help = '.map file name'
    )

    parser.add_argument( '--monitor', required = False, action = 'store_true',
        help = 'Continuously scan the .map file for changes to keep building.'
    )

    default_run_bsp = False
    parser.add_argument( '--run-bsp', required = False, action = 'store_true',
        default = default_run_bsp,
        help = 'Run BSP stage (default = {})'.format(default_run_bsp)
    )

    default_run_vis = False
    parser.add_argument( '--run-vis', required = False, action = 'store_true',
        default = default_run_vis,
        help = 'Run VIS stage (default = {})'.format(default_run_vis)
    )

    parser.add_argument( '--export-path', required = False, action = 'store',
        help = 'Copy the bsp to an additional folder after the build completes'
    )

    default_run_light_draft = False
    parser.add_argument( '--run-light-draft', required = False, action = 'store_true',
        default = default_run_light_draft,
        help = 'Run LIGHT stage with draft settings (default = {})'.format(default_run_light_draft)
    )

    conf = parser.parse_args()
    logging.basicConfig( level = logging.INFO )

    def main(build, hash):
        if (conf.verbose):
            logging.getLogger().setLevel(logging.DEBUG)

        if (build):
            if (conf.run_bsp):
                run_stage(conf.q3map2_path, conf.game_path, conf.map, 0)

            if (conf.run_vis):
                run_stage(conf.q3map2_path, conf.game_path, conf.map, 1)

            if (conf.run_light_draft):
                run_stage(conf.q3map2_path, conf.game_path, conf.map, 2)

            if (conf.export_path):
                map_root, map_extension = os.path.splitext(conf.map)
                bsp_path = map_root + ".bsp"
                copy_bsp(bsp_path, conf.export_path)

        if(conf.monitor):
            map_hash_post = md5(conf.map)
            logging.info(map_hash_post)
            time.sleep(2)
            if hash == map_hash_post:
                build = False
            else:
                build = True
            main(build, map_hash_post)
            
        

    if __name__ == "__main__":
        main(True, md5(conf.map))
