#!/usr/bin/python

from ansible.module_utils.basic import *
from ansible.module_utils.elasticsearch_api import *

class ElasticsearchUser:
    def __init__(self, api_url, api_user, api_password, name, password, roles):
        self.api = ElasticsearchApi(
            api_url,
            api_user,
            api_password
        )
        self.api_url  = api_url
        self.name     = name
        self.password = password
        self.roles    = roles
        self.exist    = False
        self.data     = {}

    def is_builtin(self):
        users = [
            'apm_system',
            'beats_system',
            'elastic',
            'kibana',
            'kibana_system',
            'logstash_system',
            'remote_monitoring_user'
        ]
        if self.name in users:
            return True

        return False

    def get_data(self):
        status_code, data = self.api.get('_security/user/{}'.format(self.name))
        if status_code == 200:
            self.exist = True
            self.data  = data[self.name]

    def roles_have_changed(self):
        for role in self.roles:
            if role not in self.data['roles']:
                return True

        for role in self.data['roles']:
            if role not in self.roles:
                return True

        return False

    def password_has_changed(self):
        api = ElasticsearchApi(
            self.api_url,
            self.name,
            self.password
        )
        status_code, _ = api.get('_cluster/health')
        if status_code == 401:
            return True

        return False

    def has_changed(self):
        if self.roles_have_changed():
            return True

        if self.password_has_changed():
            return True

        return False

    def create(self):
        self.api.put(
            '_security/user/{}'.format(self.name),
            {
                'password': self.password,
                'roles': self.roles
            }
        )

    def change_password(self):
        self.api.post(
            '_security/user/{}/_password'.format(self.name),
            {
                'password': self.password
            }
        )

    def delete(self):
        self.api.delete('_security/user/{}'.format(self.name))

        
def main():
    fields = {
        'name':         { 'type': 'str', 'required': True },
        'password':     { 'type': 'str', 'required': True, 'no_log': True },
        'roles':        { 'type': 'list', 'default': [] },
        'api_url':      { 'type': 'str', 'default': 'http://127.0.0.1:9200' },
        'api_user':     { 'type': 'str', 'default': None },
        'api_password': { 'type': 'str', 'default': None, 'no_log': True },
        'state':        { 'type': 'str', 'default': 'present', 'choice': ['present', 'absent'] },
    }
    module = AnsibleModule(argument_spec=fields)
    changed = False

    user = ElasticsearchUser(
        module.params['api_url'],
        module.params['api_user'],
        module.params['api_password'],
        module.params['name'],
        module.params['password'],
        module.params['roles'],
    )
    user.get_data()

    if user.is_builtin():
        if user.password_has_changed():
            user.change_password()
            changed = True
    else:
        if module.params['state'] == 'present':
            if not user.exist or user.has_changed():
                user.create()
                changed = True
        else:
            if user.exist:
                user.delete()
                changed = True

    module.exit_json(changed=changed)

if __name__ == '__main__':
    main()