# problem2solution_json.py
#
# ICS H32 Fall 2025
# Exercise Set 5
# INSTRUCTOR SOLUTION

import json
import urllib.request



def _download_file(url: str) -> str:
    request = urllib.request.Request(url)
    response = urllib.request.urlopen(request)

    try:
        return response.read().decode(encoding = 'utf-8')
    finally:
        response.close()



class InvalidCommandError(Exception):
    pass



class InvalidDataError(Exception):
    pass



class Location:
    def __init__(self, name: str, data: str):
        try:
            data = json.loads(data)
        except json.JSONDecodeError:
            raise InvalidDataError
        
        self._name = name

        if 'title' not in data:
            raise InvalidDataError

        self._title = data['title']

        if 'description' not in data:
            raise InvalidDataError

        self._description = ''

        for line in data['description']:
            self._description += f'{line}\n'

        if 'commands' not in data:
            raise InvalidDataError

        self._commands = {}

        for command in data['commands']:
            if 'destination' not in command or 'phrases' not in command:
                raise InvalidDataError

            for phrase in command['phrases']:
                self._commands[phrase] = command['destination']

        if 'isGameOver' in data:
            self._is_game_over = data['isGameOver']
        else:
            self._is_game_over = False



    def name(self) -> str:
        return self._name


    def title(self) -> str:
        return self._title


    def description(self) -> str:
        return self._description


    def is_game_over(self) -> bool:
        return self._is_game_over


    def get_command_destination(self, command: str) -> str:
        if command.upper() in self._commands:
            return self._commands[command.upper()]
        else:
            raise InvalidCommandError



def _read_game_url() -> str:
    print("Specify the base URL for the game you'd like to play.")
    print()
    return input('Game URL: ')



def _load_location(name: str, base_url: str) -> Location:
    return Location(name, _download_file(f'{base_url}{name}.dat'))



def run() -> None:
    base_url = _read_game_url()
    location_name = 'start'

    while True:
        try:
            location = _load_location(location_name, base_url)
        except InvalidDataError:
            print()
            print('Internal Game Error')
            print(f'The location {location_name} is represented by invalid data.')
            break

        print()
        print(location.title())
        print(location.description())

        if location.is_game_over():
            print()
            print('GAME OVER')
            break

        command = input('What would you like to do? ')

        try:
            location_name = location.get_command_destination(command)
        except InvalidCommandError:
            print('That is an invalid command.')
    


if __name__ == '__main__':
    run()
