class Policy:
    def __init__(self):
        self.id = 1
        self.name = "Policy Name"
        self.services = [ServicePolicySettings(), ServicePolicySettings()]


class ServicePolicySettings:
    def __init__(self):
        self.min_bandwidth = 10000
        self.max_bandwidth = 10000
        self.mark_dscp = "50"
        self.service = Service()


class Service:
    def __init__(self):
        self.name = "Service Name"
        self.match_ips = "10.0.0.1, 10.0.0.2, 10.0.0.3"
        self.match_tcp_ports = "50, 80, 90"
        self.match_udp_ports = "50, 80, 90"
        self.match_dscp = "50"


class Interface:
    def __init__(self):
        self.name = "FastEthernet0/0"
        self.bandwidth = 100000


def _ip_list_to_str(ip_list):
    return str(ip_list).replace("[", "").replace("]", "").replace(",", "")


def _generate_class_name(policy_name, service_name):
    return "D-{}-{}".format(policy_name.replace(" ", ""), service_name.replace(" ", ""))


def _generate_acl_name(service_name):
    return "D-{}".format(service_name.replace(" ", ""))


def _generate_policy_name(policy_name):
    return "D-{}".format(policy_name.replace(" ", ""))


def _no_spaces(text):
    return "{}".format(text.replace(" ", ""))


def apply_policy(policy, interface):
    commands = []
    description = "Dynamic Generated by Netshaping for Policy: {}".format(policy.name)

    for service_settings in policy.services:
        service = service_settings.service
        class_name = _generate_class_name(policy.name, service.name)
        if service.match_ips:
            access_list_name = _generate_acl_name(service.name)
            commands.append("ip access-list extended {}".format(access_list_name))
            for ip in service.match_ips.split(","):
                if service.match_tcp_ports or service.match_udp_ports:
                    if service.match_tcp_ports:
                        commands.append(
                            "permit tcp host {} any eq {}".format(
                                _no_spaces(ip), _ip_list_to_str(service.match_tcp_ports)
                            )
                        )
                    if service.match_udp_ports:
                        commands.append(
                            "permit udp host {} any eq {}".format(
                                _no_spaces(ip), _ip_list_to_str(service.match_udp_ports)
                            )
                        )
                else:
                    commands.append("permit ip host {} any".format(ip))
        commands.append("class-map match-any {}".format(class_name))
        if service.match_ips:
            commands.append("match access-group name {}".format(access_list_name))
        if service.match_dscp:
            for dscp in service.match_dscp.split(","):
                commands.append("match dscp {}".format(_no_spaces(dscp)))
        commands.append("policy-map {}".format(_generate_policy_name(policy.name)))
        commands.append("class {}".format(class_name))
        if service_settings.min_bandwidth:
            commands.append("bandwidth {}".format(service_settings.min_bandwidth))
        if service_settings.max_bandwidth:
            commands.append("shape average {}".format(service_settings.max_bandwidth))
        if service_settings.mark_dscp:
            commands.append("set dscp {}".format(service_settings.mark_dscp))

    commands.append("interface {}".format(interface.name))
    commands.append("bandwidth {}".format(interface.bandwidth))
    commands.append(
        "service-policy output {}".format(_generate_policy_name(policy.name))
    )
    return commands
