# coding=utf-8
"""
Neo4j Blueprint
===============

**Fabric environment:**

.. code-block:: yaml

    blueprints:
      - blues.neo4j

    settings:
      neo4j:
        # bind: 0.0.0.0  # Set the bind address specifically (Default: 0.0.0.0)
        # heap_size_mb: 512  # Set the heap size explicitly (Default: auto)

"""
from fabric.decorators import task

from refabric.api import info
from refabric.context_managers import sudo
from refabric.contrib import blueprints

from . import debian

__all__ = ['start', 'stop', 'restart', 'status', 'setup', 'configure']


blueprint = blueprints.get(__name__)

service_name = 'neo4j-service'
start = debian.service_task(service_name, 'start')
stop = debian.service_task(service_name, 'stop')
restart = debian.service_task(service_name, 'restart')
status = debian.service_task(service_name, 'status')


@task
def setup():
    """
    Install and configure Neo4j
    """
    install()
    configure()


def install():
    """
    Install Neo4j
    """
    with sudo():
        from blues import java
        java.install()

        version = blueprint.get('version', '2.2')
        info('Adding apt repository for {} version {}', 'neo4j', version)

        repository = 'http://debian.neo4j.org/repo stable/'.format(version)
        debian.add_apt_repository(repository)

        info('Adding apt key for', repository)
        debian.add_apt_key('http://debian.neo4j.org/neotechnology.gpg.key')
        debian.apt_get_update()

        debian.apt_get('install', 'neo4j')


@task
def configure():
    """
    Configure Neo4j
    """
    context = {
        'bind': blueprint.get('bind', '0.0.0.0'),
        'heap_size_mb': blueprint.get('heap_size_mb', 'auto'),
    }

    updated = False
    for f in [
        'logging.properties',
        'neo4j.properties',
        'neo4j-server.properties',
        'neo4j-wrapper.properties',
    ]:
        updated = bool(blueprint.upload(f, '/etc/neo4j/', context)) or updated

    if updated:
        restart()

@@ -156,16 +156,40 @@
  neo4j:%0A
+        password: %22hej%22%0A
         
@@ -341,16 +341,43 @@
 o)%0A%0A%22%22%22%0A
+import time%0Aimport base64%0A%0A
 from fab
@@ -402,16 +402,47 @@
 ort task
+%0Afrom fabric.utils import abort
 %0A%0Afrom r
@@ -547,16 +547,52 @@
 ueprints
+%0Afrom refabric.operations import run
 %0A%0Afrom .
@@ -618,16 +618,21 @@
 ll__ = %5B
+%0A    
 'start',
@@ -660,16 +660,20 @@
 status',
+%0A   
  'setup'
@@ -685,16 +685,45 @@
 nfigure'
+, 'install', 'set_password',%0A
 %5D%0A%0A%0Ablue
@@ -1094,17 +1094,42 @@
 igure()%0A
-%0A
+    set_password()%0A%0A%0A@task
 %0Adef ins
@@ -2171,8 +2171,1302 @@
 start()%0A
+%0A%0A@task%0Adef set_password(old_password='neo4j'):%0A    %22%22%22%0A    Sets Neo4j password%0A    %22%22%22%0A%0A    escape = lambda s: s.replace('%5C%5C', '%5C%5C%5C%5C').replace('%22', '%5C%5C%22')%0A    pw = lambda s: base64.b64encode('neo4j:' + s)%0A%0A    new_password = blueprint.get('password')%0A    assert new_password%0A%0A    info(%22Checking password%22)%0A    output = run('curl http://localhost:7474/user/neo4j '%0A                 '-H %22Authorization: Basic %25s%22' %25 pw(new_password))%0A%0A    if '%22username%22 : %22neo4j%22' not in output:%0A        if 'AuthorizationFailed' in output:%0A            info(%22Waiting 5 sec due to Jetty's bruteforce protection%22)%0A            time.sleep(5)%0A%0A        info(%22Setting password%22)%0A        assert old_password%0A%0A        # TODO: it did not work with %60-U neo4j:%25s%60 why?%0A        output = run(%0A            'curl -X POST http://localhost:7474/user/neo4j/password'%0A            '-H %22Accept: application/json; charset=UTF-8%22 '%0A            '-H %22Content-Type: application/json%22 '%0A            '-H %22Authorization: Basic %25s%22 '%0A            '-d %5C'%7B%22password%22 : %22%25s%22%7D%5C' ' %25 (%0A                pw(old_password), escape(new_password)))%0A%0A        if 'AuthorizationFailed' in output:%0A            abort(%22Wrong current Neo4j password, cannot change it%22)%0A%0A        elif '%22username%22 : %22neo4j%22' not in output:%0A            abort(%22Unexpected response%22)%0A

Set password