import logging
import functools
import time

from apscheduler.schedulers.background import BackgroundScheduler
import boto3
import botocore
from pyformance import timer
from pytz import utc

from groundcontrol.models import DeploymentModel
from groundcontrol.instrument.metrics import metric
from groundcontrol.helpers import Flyby


logger = logging.getLogger()
metrics = logging.getLogger('metrics')


class BackgroundJob:

    @classmethod
    def run(cls, region_name='eu-west-1', flyby_endpoint=''):
        flyby = Flyby(flyby_endpoint) if flyby_endpoint else None
        start_time = time.time()
        active_services_count = 0
        draining_services_count = 0
        inactive_services_count = 0
        # This dictionary holds the list of host addresses grouped by
        # loadbalancer name and target group name
        backends = {}
        service_lb_backends = cls._get_flyby_backends(flyby)
        with DeploymentModel.batch_write() as batch:
            for deployment in DeploymentModel.scan(active__eq=True):
                # If it looks like the load balancer is unreachable for any reason make no attempt
                # to try and scale a load balanced service
                try:
                    tasks = cls.task_details(deployment, region_name)
                    if service_lb_backends and service_lb_backends.get('failures', None) and getattr(
                            deployment, "loadbalancer_config", None):
                        logger.error(
                            "Service ({}) on cluster ({}) has load balancer config defined but the load balancer ({}) "
                            "does not appear available or responding as expected - skipping scaling actions".format(
                                deployment.service, deployment.cluster, flyby))
                        metrics.error(metric(
                            'scheduler.loadbalancer.errors', 1, error='unreachable',
                            service=deployment.service, cluster=deployment.cluster
                        ))
                    else:
                        lb_info = cls._get_lb_info(