#!/usr/bin/env python
"""
    Parses jail booking data files provided by the Palm Beach Sheriff's Office.

    This script takes an XML file provided by the sheriff's office, parses it and outputs a flattened CSV file named the same as the XML file. The script is run via the command line and accepts the name of the XML file as an argument, like so:
    python pbso_jail_records.py myfilename.xml

    Author: Danny Sanchez, South Florida Sun Sentinel, dsanchez@sun-sentinel.com
"""

import sys
import csv
from termcolor import colored
from bs4 import BeautifulSoup

print("Parsing jail data file...")

try:
    filename = sys.argv[1]
except IndexError:
    print(colored("Error: Please provide a filename to parse.", "red", attrs=['reverse']))
    sys.exit()

try:
    with open(filename, 'r') as myfile:
        data = myfile.read().replace('\n', '')
        soup = BeautifulSoup("<Bookings>" + data + "</Bookings>", "xml")  # Needs a root tag added.

except OSError:
    print(colored("Error:", "red", attrs=['reverse']) + colored(" The provided file was not found.", "red"))
    sys.exit()

booking_data = soup.find_all("Booking")

item_counter = 0

csv_fieldnames = ["FullName", "birthdate", "Race", "address1", "city", "state", "zipcode", "BookingDate", "BookingTime", "BookingId", "Jacket", "InmateFirst", "InmateMiddle", "InmateLast", "InmateSuffix", "ReleaseDate", "ReleaseTime", "Gender", "ArrestingAgency", "ChargeCode", "ChargeDescription", "currentbond", "bondamount", "OBTS", "facility", "cell", "holdotheragencies"]

with open(filename.replace(".xml", "") + ".csv", 'w', newline='') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=csv_fieldnames)
    writer.writeheader()

    """
    The tag structure in the jail file is <Booking><Cases><Charges><BIO>

    The Booking tag contains biographical details. Inmates can have multiple cases and multiple charges within a case. It's a tree of one-to-manys. The BIOs all seem to be dupes, so this script just gets the first one.
    """
    for booking in booking_data:

        booking_attributes = ["FullName", "birthdate", "Race", "address1", "city", "state", "zipcode", "BookingDate", "BookingTime", "BookingId", "Jacket", "InmateFirst", "InmateMiddle", "InmateLast", "InmateSuffix", "ReleaseDate", "ReleaseTime", "Gender"]

        charge_attributes = ["ChargeCode", "ChargeDescription", "currentbond", "bondamount"]

        bio_attributes = ["OBTS", "facility", "cell", "holdotheragencies"]

        # Set an empty string to catch missing attributes in the data file.
        for attribute in booking_attributes:
            if booking.has_attr(attribute) is False:
                booking[attribute] = ""
            else:
                booking[attribute] = booking[attribute].strip()

        # Drill down into the list of cases.
        cases = booking.find_all("Cases")
        for case in cases:
            if case.has_attr("ArrestingAgency") is False:
                case["ArrestingAgency"] = ""
            else:
                case["ArrestingAgency"] = case["ArrestingAgency"].strip()

            # Drill down into the charges for the case.
            charges = case.find_all("Charges")
            for charge in charges:
                for attribute in charge_attributes:
                    if charge.has_attr(attribute) is False:
                        charge[attribute] = ""
                    else:
                        charge[attribute] = charge[attribute].strip()

                # Drill down into the bio for the case.
                bio = charge.find("BIO")  # Just get the first one

                for attribute in bio_attributes:
                    if bio.has_attr(attribute) is False:
                        bio[attribute] = ""
                    else:
                        bio[attribute] = bio[attribute].strip()

                writer.writerow({
                    "FullName": booking['FullName'],
                    "birthdate": booking['birthdate'],
                    "Race": booking['Race'],
                    "address1": booking['address1'],
                    "city": booking['city'],
                    "state": booking['state'],
                    "zipcode": booking['zipcode'],
                    "BookingDate": booking['BookingDate'],
                    "BookingTime": booking['BookingTime'],
                    "BookingId": booking['BookingId'],
                    "Jacket": booking['Jacket'],
                    "InmateFirst": booking['InmateFirst'],
                    "InmateMiddle": booking['InmateMiddle'],
                    "InmateLast": booking['InmateLast'],
                    "InmateSuffix": booking['InmateSuffix'],
                    "ReleaseDate": booking['ReleaseDate'],
                    "ReleaseTime": booking['ReleaseTime'],
                    "Gender": booking['Gender'],
                    "ArrestingAgency": case["ArrestingAgency"],
                    "ChargeCode": charge['ChargeCode'],
                    "ChargeDescription": charge['ChargeDescription'],
                    "currentbond": charge['currentbond'],
                    "bondamount": charge['bondamount'],
                    "OBTS": bio['OBTS'],
                    "facility": bio['facility'],
                    "cell": bio['cell'],
                    "holdotheragencies": bio['holdotheragencies']
                })

        item_counter += 1

print("Number of bookings: " + "{:,}".format(item_counter))
