#!/usr/bin/python3

REQUIRED_FIELDS=(('byr', "Birth Year"),('iyr', "Issue Year"),('eyr', "Expiration Year"),('hgt', "Height"),('hcl', "Hair Colour"),('ecl', "Eye Colour"),('pid',"Passport ID"))
OPTIONAL_FIELDS=(('cid', "Country ID"))
VALID_EYE_COLOURS=('amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth')

def check_passport(passport_data):
    print(passport_data)
    for field in REQUIRED_FIELDS:
        if field[0] not in passport_data:
            return False
        # check the field data
        if field[0] == 'byr':
            if not check_year(passport_data[field[0]], 1920, 2002):
                return False
        elif field[0] == 'iyr':
            if not check_year(passport_data[field[0]], 2010, 2020):
                return False
        elif field[0] == 'eyr':
            if not check_year(passport_data[field[0]], 2020, 2030):
                return False
        elif field[0] == 'hgt':
            if not check_height(passport_data[field[0]]):
                return False
        elif field[0] == 'hcl':
            if not check_hair_colour(passport_data[field[0]]):
                return False
        elif field[0] == 'ecl':
            if not passport_data[field[0]] in VALID_EYE_COLOURS:
                return False
        elif field[0] == 'pid':
            if not check_pid(passport_data[field[0]]):
                return False
    return True

def check_year(data, min_year, max_year):
    try:
        year = int(data)
        if year >= min_year and year <= max_year:
            return True
        return False
    except:
        return False

def check_height(data):
    try:
        unit = data[-2:]
        value = int(data[:-2])

        if unit == "cm":
            if value >= 150 and value <= 193:
                return True
        elif unit == "in":
            if value >= 59 and value <= 76:
                return True
        return False
    except:
        return False

def check_hair_colour(data):
    if data[0] != "#":
        return False
    if len(data) != 7:
        return False
    if data != data.lower():
        return False
    try:
        value = int(data[1:], 16)
        return True
    except:
        return False
    return False

def check_pid(data):
    # first check that the string length is correct
    if len(data) != 9:
        return False

    # now check that it's a number
    try:
        int(data, 10)
        return True
    except:
        return False

def main():
    new_passport=False
    passport_data=dict()
    valid_passports=0
    for line in open("input.txt"):
        if new_passport:
            if check_passport(passport_data):
                valid_passports += 1
            passport_data.clear()
        line=line.rstrip()
        if line == '':
            new_passport=True
            continue
        new_passport=False
        parts=line.split(" ")
        for part in parts:
            (key, value) = part.split(":")
            passport_data[key] = value
    if not new_passport:
        if check_passport(passport_data):
            valid_passports += 1
    print("Found", valid_passports, "valid passports")

main()
