###
# Setup:

# Step 1: Install requirements from PIP

# Run `pip` to install requirements:
# `pip install mss opencv-python PyAutoGUI pytesseract PyDirectInput`

# Step 2: Install Tesseract-OCR

# https://github.com/UB-Mannheim/tesseract/wiki#tesseract-installer-for-windows
# Select `tesseract-ocr-w64-setup-5.4.0.20240606.exe`
# Newer version may have a different name
# Keep its original installation path at `C:\Program Files\Tesseract-OCR`

# Step 3: Install CapFrameX

# Download CapFrameX:
# https://github.com/CXWorld/CapFrameX/releases/latest
# Portable version is recommended
# Open CapFrameX and set capture time to `0` for unlimited recording time
# Click on Settings in top right and change "Capture File Mode" from `JSON` to `JSON+CSV`
# Go to Overlay Tab, Find OSD Options (hamburger menu, 3 dots) next to group control
# and Untick `Auto-Disable OSD`
###

###
# Note that it is not possible yet to include comments to assoicate with run config files for now
# So all captures will have generic name of `CapFrameX-ForzaHorizon5.exe-(Year)-(Month)-(Day)(...).csv`
###

###
# Config file array list
# Amount of files listed here is what will be ran until completion
# I.e 4 config files = 4 runs
# Input your path after `R` prefix within the quotations
###

config_list = [
    R"C:\benchmarking\UserConfigSelections_720pHigh",
    R"C:\benchmarking\UserConfigSelections_1080pHigh",
    R"C:\benchmarking\UserConfigSelections_1440pHigh",
    R"C:\benchmarking\UserConfigSelections_2160pHigh"
]

# This is for starting the data capture
# If you want to change it, make sure it matches your data capturing program
# If it is F11 here, it should be set the same in data capture provider.
# F11 is CapFrameX default
start_data_provider_capture_key = 'F11'

## Automation method: OCR

import cv2
import pytesseract
import pyautogui
import mss
import numpy as np
import time
import os
import shutil
from datetime import datetime
import subprocess

pytesseract.pytesseract.tesseract_cmd = R"C:\Program Files\Tesseract-OCR\tesseract.exe"

APPDATALOCAL = os.getenv("LOCALAPPDATA")
CONFIG_LOCATION = (
    f"{APPDATALOCAL}\\ForzaHorizon5\\User_SteamLocalStorageDirectory"
    "\\ConnectedStorage\\ForzaUserConfigSelections"
)
CONFIG_FILENAME = "UserConfigSelections"

now = datetime.now()
dt_string = now.strftime("%d_%m_%Y_%H_%M_%S")

original_file = f'{CONFIG_LOCATION}\\{CONFIG_FILENAME}'
backup_file = f'{CONFIG_LOCATION}\\{CONFIG_FILENAME}_backup_{dt_string}'

def key_press(key):
    pyautogui.press(key)

def handle_forza_horizon_5():
    w, h = pyautogui.size()
    print(f'display 0 width: {w}x{h}')
    StopProgram = False
    print("loop begin")
    time.sleep(1)
    print("loop start")
    stepBoot = False
    stepOptions = False
    stepBenchmarkEnter = False
    stepBenchmarkStart = False
    with mss.mss() as sct:
        monitor = {"top": 0, "left": 0, "width": w, "height": h}
        while not StopProgram:
            img2 = cv2.resize(np.array(sct.grab(monitor)), (w//2, h//2))
            gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
            cv2.imwrite('temp_bw.png', gray) # avoid `pytesseract.image_to_string` saving to temp folder
            text = pytesseract.image_to_string('temp_bw.png')
            if text.find("Start Game") > 0 or text.find("START GAME") > 0:
                if stepBoot is False:
                    print("Found Start Game")
                    key_press('enter')
                    stepBoot = True
            if text.find("Sign Out") > 0 or text.find("Options") > 0:
                if stepOptions is False:
                    print("options")
                    # Scroll to options
                    key_press('down')
                    time.sleep(0.1)
                    # Enter to settings
                    key_press('enter')
                    time.sleep(0.4)
                    # Scroll to graphics option
                    for i in range(0, 7):
                        key_press('down')
                        time.sleep(0.3)
                    key_press('enter')
                    stepOptions = True
            elif text.find("BENCHMARK MODE") > 0:
                if stepBenchmarkEnter is False:
                    print("benchmark")
                    key_press('enter')
                    time.sleep(0.2)
                    key_press('down')
                    time.sleep(0.2)
                    key_press('enter')
                    time.sleep(0.2)
                    stepBenchmarkEnter = True
                    # Start data capture after starting to load benchmark
                    key_press(start_data_provider_capture_key)
            elif text.find('12/12') > 0 or text.find('GO!') > 0:
                if stepBenchmarkStart is False:
                    print("benchmark started")
                    time.sleep(93)
                    key_press(start_data_provider_capture_key)
                    print("benchmark finished")
                    # wait for cx to process its data
                    time.sleep(5)
                    os.system("taskkill /f /im ForzaHorizon5.exe")
                    stepBenchmarkStart = True
                    StopProgram = True
            time.sleep(0.0667)

def main():
    shutil.copy2(original_file, backup_file)
    print(f'Backup of original config: {backup_file}')
    for config in config_list:
        print(f'Running with config: {config}')
        shutil.copy2(config, original_file)
        print(f'Config copied: {config}')
        subprocess.run("start steam://rungameid/1551360", shell=True)
        handle_forza_horizon_5()
    
    shutil.copy2(backup_file, original_file)
    print(f'Original config restored: {backup_file}')

if __name__ == "__main__":
    main()
