# problem2solution.py
#
# ICS H32 Fall 2025
# Exercise Set 3
# INSTRUCTOR SOLUTION

from collections import namedtuple


_Point = namedtuple('Point', ['x', 'y', 'z'])
_Person = namedtuple('Person', ['name', 'age', 'favorite'])
_Team = namedtuple('Team', ['home_location', 'name'])



def _max_field_length(value: 'namedtuple') -> int:
    '''
    Given a namedtuple, returns the maximum length of the fields' names
    '''
    max_len = -1

    for field in value._fields:
        if len(field) > max_len:
            max_len = len(field)

    return max_len


assert _max_field_length(_Point(1, 2, 3)) == len('x')
assert _max_field_length(_Person('Boo', 13, 'Alex')) == len('favorite')
assert _max_field_length(_Team('UC Irvine', 'Anteaters')) == len('home_location')



def _pad_string(s: str, desired_length: int) -> str:
    '''
    Pads a string by adding spaces to the front of it, if needed,
    so it becomes the desired length, returning the padded version
    of the string.  If the string is already at least the desired
    length, it is returned unchanged.
    '''
    if len(s) >= desired_length:
        return s
    else:
        padding = ' ' * (desired_length - len(s))
        return padding + s


assert _pad_string('Alex', 10) == '      Alex'
assert _pad_string('example', 8) == ' example'
assert _pad_string('Boo', 3) == 'Boo'
assert _pad_string('hello', 4) == 'hello'



def _format_field(field_name: str, field_value, max_field_name_len: int) -> str:
    '''
    Formats one field of a namedtuple, given the field's name, its
    value, and the length of the longest field name in the namedtuple.
    '''
    padded_field_name = _pad_string(field_name, max_field_name_len)
    return f'{padded_field_name}: {field_value}'


assert _format_field('nickname', 'Someone', 10) == '  nickname: Someone'
assert _format_field('name', 'Alex', 4) == 'name: Alex'
assert _format_field('name', 'Alex', 3) == 'name: Alex'



def _pretty_print_lines(value: 'namedtuple') -> list[str]:
    '''
    Given a namedtuple, returns a list of strings containing a pretty-
    printed version of a namedtuple
    '''
    max_len = _max_field_length(value)
    lines = []
    
    for field_num in range(len(value._fields)):
        lines.append(_format_field(value._fields[field_num], value[field_num], max_len))

    return lines


assert _pretty_print_lines(_Point(x = 3, y = 5, z = 7)) == ['x: 3', 'y: 5', 'z: 7']

assert _pretty_print_lines(_Person(name = 'Alex', age = 45, favorite = 'Boo')) \
    == ['    name: Alex', '     age: 45', 'favorite: Boo']

assert _pretty_print_lines(_Team(home_location = 'UC Irvine', name = 'Anteaters')) \
    == ['home_location: UC Irvine', '         name: Anteaters']



def pretty_print(value: 'namedtuple') -> None:
    'Given a namedtuple, pretty-prints it to the standard output'
    for line in _pretty_print_lines(value):
        print(line)
