#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGESWHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.

"""
bump_roll.py

usage:
    ./util/bump_roll.py <week> <roll>
example:
    ./util/bump_roll.py 1970-24 r16
"""

import argparse
import subprocess
import re
import sys
from pathlib import Path


ROLL_PATTERN = re.compile(r'(\broll\s*=\s*)(\d+)(\s*,)', flags=re.IGNORECASE)
WEEK_PATTERN = re.compile(r'(\bweek\s*=\s*)(".*?"|\'.*?\')(\s*,?)', flags=re.IGNORECASE)


def run(*args, check=True, allow_fail=False):
    print(f"> {' '.join(args)}")
    try:
        subprocess.check_call(args)
    except subprocess.CalledProcessError as e:
        if allow_fail:
            print(f"warning: command failed but continuing: {e}")
            return e.returncode
        else:
            print(f"error: command failed: {e}")
            sys.exit(e.returncode)

def main():
    parser = argparse.ArgumentParser(description="bump Voxelgarden version in mods/vg_init/init.lua")
    parser.add_argument("week", help='week string like 1970-24')
    parser.add_argument("roll", help='roll like r16 or 16')
    args = parser.parse_args()

    # parse roll number
    roll_str = args.roll.lower().lstrip("r")
    if not roll_str.isdigit():
        print("error: roll must be numeric or start with 'r' followed by digits (e.g. r16).")
        sys.exit(1)
    roll = roll_str
    week = args.week

    # locate target file relative to this script's parent folder
    script_dir = Path(__file__).resolve().parent
    game_root = script_dir.parent
    target = game_root / "mods" / "vg_init" / "init.lua"

    if not target.exists():
        print(f"error: target file not found at {target}")
        sys.exit(2)

    # delete local bump branch if exists
    run("git", "branch", "-D", "bump", allow_fail=True)

    # check for and pull remote changes
    run("git", "checkout", "master")
    run("git", "pull")

    # branch out locally
    run("git", "checkout", "-b", "bump")

    # read and update file
    text = target.read_text(encoding="utf-8")

    text_new, n_roll = ROLL_PATTERN.subn(lambda m: f'{m.group(1)}{roll}{m.group(3)}', text)
    text_new, n_week = WEEK_PATTERN.subn(lambda m: f'{m.group(1)}"{week}"{m.group(3) or ""}', text_new)

    if n_roll == 0 and n_week == 0:
        print("error: no replacements made -- file format may differ from expected. aborting.")
        sys.exit(3)

    # write backup and write file
    backup = target.with_suffix(target.suffix + ".bak")
    backup.write_text(text, encoding="utf-8")
    target.write_text(text_new, encoding="utf-8")
    print(f"updated {target} (roll replacements: {n_roll}, week replacements: {n_week}). backup: {backup.name}")

    # commit changes
    run("git", "add", str(target))
    commit_msg = f"vg_init: Bump to {week} r{roll}"
    run("git", "commit", "-m", commit_msg)

    # create PR via AGit
    run("git", "push", "origin", "HEAD:refs/for/master", "-o", 'topic="bump"')

    print("done. visit the PR by following the link returned by the remote and merge if nothing is messed up!")


if __name__ == "__main__":
    main()
