#!/usr/bin/env python

from __future__ import absolute_import
from __future__ import unicode_literals
import sys
import os
import mimetypes
from collections import namedtuple
import six

import django

GeventCommand = namedtuple('GeventCommand', 'command contains')


def _set_source_root_parent(source_root_parent):
    """
    add everything under `source_root_parent` to the list of source roots
    e.g. if you call this with param 'submodules'
    and you have the file structure

    project/
        submodules/
            foo-src/
                foo/
            bar-src/
                bar/

    (where foo and bar are python modules)
    then foo and bar would become top-level importable

    """
    filedir = os.path.dirname(__file__)
    submodules_list = os.listdir(os.path.join(filedir, source_root_parent))
    for d in submodules_list:
        if d == "__init__.py" or d == '.' or d == '..':
            continue
        sys.path.insert(1, os.path.join(filedir, source_root_parent, d))

    sys.path.append(os.path.join(filedir, source_root_parent))


def _set_source_root(source_root):
    filedir = os.path.dirname(__file__)
    sys.path.insert(1, os.path.join(filedir, source_root))


# HACK monkey-patch django setup to prevent second setup by django_nose
def _setup_once(*args, **kw):
    if not hasattr(_setup_once, "done"):
        _setup_once.done = True
        _setup_once.setup(*args, **kw)


_setup_once.setup = django.setup
django.setup = _setup_once


def init_hq_python_path():
    _set_source_root_parent('submodules')
    _set_source_root(os.path.join('corehq', 'ex-submodules'))
    _set_source_root(os.path.join('custom', '_legacy'))


def _should_patch_gevent(args, gevent_commands):
    should_patch = False
    for gevent_command in gevent_commands:
        should_patch = args[1] == gevent_command.command
        if gevent_command.contains:
            should_patch = should_patch and gevent_command.contains in ' '.join(args)
        if should_patch:
            break
    return should_patch


def set_default_settings_path(argv):
    if len(argv) > 1 and argv[1] == 'test' or os.environ.get('CCHQ_TESTING') == '1':
        os.environ.setdefault('CCHQ_TESTING', '1')
        module = 'testsettings'
    else:
        module = 'settings'
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", module)


def patch_jsonfield():
    """Patch the ``to_python`` method of JSONField
    See https://github.com/bradjasper/django-jsonfield/pull/173 for more details
    """
    import six
    import json
    from django.core.exceptions import ValidationError
    from django.utils.translation import ugettext_lazy as _
    from jsonfield import JSONField

    def to_python(self, value):
        if isinstance(value, six.string_types):
            try:
                return json.loads(value, **self.load_kwargs)
            except ValueError:
                raise ValidationError(_("Enter valid JSON"))
        return value

    JSONField.to_python = to_python


def patch_assertItemsEqual():
    import unittest
    if six.PY3:
        unittest.TestCase.assertItemsEqual = unittest.TestCase.assertCountEqual


if __name__ == "__main__":
    init_hq_python_path()

    # important to apply gevent monkey patches before running any other code
    # applying this later can lead to inconsistencies and threading issues
    # but compressor doesn't like it
    # ('module' object has no attribute 'poll' which has to do with
    # gevent-patching subprocess)
    GEVENT_COMMANDS = (
        GeventCommand('mvp_force_update', None),
        GeventCommand('run_gunicorn', None),
        GeventCommand('run_sql', None),
        GeventCommand('preindex_everything', None),
        GeventCommand('migrate_multi', None),
        GeventCommand('prime_views', None),
        GeventCommand('ptop_preindex', None),
        GeventCommand('sync_prepare_couchdb_multi', None),
        GeventCommand('sync_couch_views', None),
        GeventCommand('celery', '-P gevent'),
        GeventCommand('populate_form_date_modified', None),
        GeventCommand('migrate_domain_from_couch_to_sql', None),
        GeventCommand('migrate_multiple_domains_from_couch_to_sql', None),
    )
    if len(sys.argv) > 1 and _should_patch_gevent(sys.argv, GEVENT_COMMANDS):
        from gevent.monkey import patch_all; patch_all(subprocess=True)
        from psycogreen.gevent import patch_psycopg; patch_psycopg()

    # workaround for https://github.com/smore-inc/tinys3/issues/33
    mimetypes.init()
    patch_jsonfield()

    patch_assertItemsEqual()

    set_default_settings_path(sys.argv)
    from django.core.management import execute_from_command_line
    execute_from_command_line(sys.argv)

@@ -178,16 +178,32 @@
 port six
+%0Aimport requests
 %0A%0Aimport
@@ -272,16 +272,39 @@
 contains
+ http_adapter_pool_size
 ')%0A%0A%0Adef
@@ -2029,16 +2029,161 @@
 _patch:%0A
+            if gevent_command.http_adapter_pool_size:%0A                requests.adapters.DEFAULT_POOLSIZE = gevent_command.http_adapter_pool_size%0A
         
@@ -3738,24 +3738,27 @@
 pdate', None
+, 0
 ),%0A        G
@@ -3786,24 +3786,27 @@
 icorn', None
+, 0
 ),%0A        G
@@ -3825,32 +3825,35 @@
 ('run_sql', None
+, 0
 ),%0A        Geven
@@ -3884,24 +3884,27 @@
 thing', None
+, 0
 ),%0A        G
@@ -3929,32 +3929,35 @@
 ate_multi', None
+, 0
 ),%0A        Geven
@@ -3976,32 +3976,35 @@
 ime_views', None
+, 0
 ),%0A        Geven
@@ -4029,24 +4029,27 @@
 index', None
+, 0
 ),%0A        G
@@ -4091,24 +4091,27 @@
 multi', None
+, 0
 ),%0A        G
@@ -4143,24 +4143,27 @@
 views', None
+, 0
 ),%0A        G
@@ -4196,16 +4196,19 @@
  gevent'
+, 0
 ),%0A     
@@ -4255,24 +4255,27 @@
 ified', None
+, 0
 ),%0A        G
@@ -4323,24 +4323,28 @@
 o_sql', None
+, 32
 ),%0A        G
@@ -4406,16 +4406,20 @@
 l', None
+, 32
 ),%0A    )

increase connection pool size for migrations