# -*- coding: utf-8 -*-

from requests import Session
from requests.adapters import HTTPAdapter
from functools import partial

from blackgate.executor_pools  import ExecutorPools
from blackgate.circuit_beaker import NoCircuitBeaker, InProcessCircuitBeaker, get_circuit_beaker

class Component(object):

    def __init__(self):
        self.session = Session()
        self.urls = []
        self.pools = ExecutorPools()
        self.circuit_beakers = {}
        self.circuit_beaker_impl = NoCircuitBeaker
        self.circuit_beaker_options = {}
        self.get_circuit_beaker = partial(
            get_circuit_beaker,
            self.circuit_beakers,
        )
        self.configurations = {}
        self.configurations.setdefault('urls', [])

    @property
    def config(self):
        return self.configurations

    def set(self, key, value):
        self.configurations[key] = value

    def add(self, key, value):
        self.configurations.setdefault(key, [])
        if key in self.configurations:
            assert isinstance(self.configurations[key], list)
        self.configurations[key].append(value)

    def delete(self, key):
        del self.configurations[key]

    def install(self):
        self.install_executor_pool()
        self.install_circuit_beaker()
        self.install_session()
        self.install_tornado_urls()

    def install_executor_pool(self):
        self.pools.register_pool('default', 1)

        if 'executor_pool' in self.configurations:
            for executor_pool in self.configurations['executor_pool']:
                self.pools.register_pool(executor_pool['group_key'], executor_pool['max_workers'])

    def install_circuit_beaker(self):
        if 'circuit_beaker_enabled' in self.configurations:
            self.circuit_beaker_impl = NoCircuitBeaker
            self.circuit_beaker_options = {}
        elif 'circuit_beaker_impl' not in self.configurations:
            self.circuit_beaker_impl = InProcessCircuitBeaker
            self.circuit_beaker_options = {'metrics': None} # FIXME
        else:
            # FIXME: add definition of import_string
            self.circuit_beaker_impl = import_string(self.configurations['circuit_beaker_impl'])
            self.circuit_beaker_options = self.configurations.get('circuit_beaker_options') or {}

    def install_session(self):
        if 'requests_session_mounts' not in self.configurations:
            return

        for mount in self.configurations['requests_session_mounts']:
            pool_connections = mount.get('pool_connections') or 10
            pool_maxsize = mount.get('pool_maxsize') or 10
            max_retries = mount.get('max_retries') or 0
            pool_block = mount.get('pool_block') or False
            prefix = mount['prefix']
            self.session.mount(prefix, HTTPAdapter(
                pool_connections=pool_connections,
                pool_maxsize=pool_maxsize,
                max_retries=max_retries,
                pool_block=pool_block,
            ))

    def install_tornado_urls(self):
        from blackgate.http_proxy import HTTPProxy
        from blackgate.command import HTTPProxyCommand

        for proxy in self.configurations.get('proxies', []):
            route = [
                proxy['request_path_regex'],
                HTTPProxy,
                dict(command=HTTPProxyCommand, proxy=proxy),
            ]
            self.urls.append(route)

@@ -1396,254 +1396,175 @@
     
-self.pools.register_pool('default', 1)%0A%0A        if 'executor_pool' in self.configurations:%0A            for executor_pool in self.configurations%5B'executor_pool'%5D:%0A                self.pools.register_pool(executor_pool%5B'group_key'%5D, executor_pool%5B'
+for proxy in self.configurations.get('proxies', %5B%5D):%0A            max_workers = proxy.get('pool_max_workers') or 10%0A            self.pools.register_pool(proxy%5B'name'%5D, 
 max_
@@ -1570,18 +1570,16 @@
 _workers
-'%5D
 )%0A%0A    d
@@ -2270,152 +2270,59 @@
     
-if 'requests_session_mounts' not in self.configurations:%0A            return%0A%0A        for mount in self.configurations%5B'requests_session_mounts'%5D
+for proxy in self.configurations.get('proxies', %5B%5D)
 :%0A  
@@ -2346,29 +2346,29 @@
 nnections = 
-mount
+proxy
 .get('pool_c
@@ -2413,21 +2413,21 @@
 xsize = 
-mount
+proxy
 .get('po
@@ -2428,24 +2428,25 @@
 et('pool_max
+_
 size') or 10
@@ -2472,21 +2472,21 @@
 tries = 
-mount
+proxy
 .get('ma
@@ -2527,21 +2527,21 @@
 block = 
-mount
+proxy
 .get('po
@@ -2585,21 +2585,27 @@
 x = 
-mount%5B'prefix
+proxy%5B'upstream_url
 '%5D%0A 

install component executor pool and session from proxies field.