#!/usr/bin/env python3

""" Generate the default values for the SUMOActivityGen.

    Author: Lara CODECA

    This program and the accompanying materials are made available under the
    terms of the Eclipse Public License 2.0 which is available at
    http://www.eclipse.org/legal/epl-2.0.
"""

import argparse
import json
import sys
import xml.etree.ElementTree


def get_options(cmd_args=None):
    """Argument Parser"""
    parser = argparse.ArgumentParser(
        prog="generateDefaultsActivityGen.py",
        usage="%(prog)s [options]",
        description="Generate the default values for the SUMOActivityGen.",
    )
    parser.add_argument(
        "--conf",
        type=str,
        dest="conf_file",
        required=True,
        help="Default configuration file.",
    )
    parser.add_argument(
        "--od-amitran",
        type=str,
        dest="amitran_file",
        required=True,
        help="OD matrix in Amitran format.",
    )
    parser.add_argument(
        "--out", type=str, dest="output", required=True, help="Output file."
    )
    parser.add_argument(
        "--population",
        type=int,
        dest="population",
        default=1000,
        help="Population: number of entities to generate.",
    )
    parser.add_argument(
        "--taxi-fleet",
        type=int,
        dest="taxi_fleet",
        default=10,
        help="Size of the taxi fleet.",
    )
    return parser.parse_args(cmd_args)


class ActivitygenDefaultGenerator:
    """Generate the default values for SUMOActivityGen."""

    def __init__(self, options):

        self._options = options
        self._config_struct = None
        self._amitran_struct = None
        self._load_configurations()
        self._set_taxi_fleet()
        self._load_odmatrix()
        self._generate_taz()
        self._generate_slices()

    def _load_configurations(self):
        """Load JSON configuration file in a dict."""
        self._config_struct = json.loads(open(self._options.conf_file).read())

    def _set_taxi_fleet(self):
        """Setup the taxi fleet."""
        self._config_struct["intermodalOptions"][
            "taxiFleetSize"
        ] = self._options.taxi_fleet

    def _load_odmatrix(self):
        """Load the Amitran XML configuration file."""
        self._amitran_struct = self._parse_xml_file(self._options.amitran_file)

    def _generate_slices(self):
        """Generate population and slices from Amitran definition."""
        population = 0.0
        for odpair in self._amitran_struct:
            population += float(odpair["amount"])

        for odpair in self._amitran_struct:
            perc = round(float(odpair["amount"]) / population, 4)
            if perc <= 0:
                continue
            slice_name = "{}_{}".format(odpair["origin"], odpair["destination"])
            self._config_struct["slices"][slice_name] = {
                "perc": perc,
                "loc_origin": odpair["origin"],
                "loc_primary": odpair["destination"],
                "activityChains": self._config_struct["slices"]["default"][
                    "activityChains"
                ],
            }

        self._config_struct["slices"].pop("default", None)
        self._config_struct["population"]["entities"] = self._options.population

    def _generate_taz(self):
        """Generate TAZ from Amitran definition."""
        for odpair in self._amitran_struct:
            self._config_struct["taz"][odpair["origin"]] = [odpair["origin"]]
            self._config_struct["taz"][odpair["destination"]] = [odpair["destination"]]

    @staticmethod
    def _parse_xml_file(xml_file):
        """Extract all odPair info from an Amitran XML file."""
        xml_tree = xml.etree.ElementTree.parse(xml_file).getroot()
        list_xml = list()
        for child in xml_tree.iter("odPair"):
            parsed = {}
            for key, value in child.attrib.items():
                parsed[key] = value
            list_xml.append(parsed)
        return list_xml

    def save_configuration_file(self, filename):
        """Save the configuration file."""
        print("Creation of {}".format(filename))
        with open(filename, "w") as outfile:
            outfile.write(json.dumps(self._config_struct, indent=4))
        print("{} created.".format(filename))


def main(cmd_args):
    """Generate the default values for SUMOActivityGen."""
    options = get_options(cmd_args)

    defaults = ActivitygenDefaultGenerator(options)
    defaults.save_configuration_file(options.output)

    print("Done.")


if __name__ == "__main__":
    main(sys.argv[1:])
