Initial change of Zabbix Admin password to password taken from one of the sources (only the most prioritized one):
        1. 'password' parameter
        2. '_connection_password' parameter
        3. pillar 'zabbix.password' setting

    1) Tries to log in as Admin with password found in state password parameter or _connection_password
       or pillar or default zabbix password in this precise order, if any of them is present.
    2) If one of above passwords matches, it tries to change the password to the most prioritized one.
    3) If not able to connect with any password then it fails.

    :param name: Just a name of state
    :param password: Optional - desired password for Admin to be set
    :param _connection_user: Optional - Ignored in this state (always assumed 'Admin')
    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)

    .. code-block:: yaml

        # password taken from pillar or _connection_password
        zabbix-admin-password:
            zabbix_user.admin_password_present

        # directly set password
        zabbix-admin-password:
            zabbix_user.admin_password_present:
                - password: SECRET_PASS

def admin_password_present(name, password=None, **kwargs):
    '''
    Initial change of Zabbix Admin password to password taken from one of the sources (only the most prioritized one):
        1. 'password' parameter
        2. '_connection_password' parameter
        3. pillar 'zabbix.password' setting

    1) Tries to log in as Admin with password found in state password parameter or _connection_password
       or pillar or default zabbix password in this precise order, if any of them is present.
    2) If one of above passwords matches, it tries to change the password to the most prioritized one.
    3) If not able to connect with any password then it fails.

    :param name: Just a name of state
    :param password: Optional - desired password for Admin to be set
    :param _connection_user: Optional - Ignored in this state (always assumed 'Admin')
    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)

    .. code-block:: yaml

        # password taken from pillar or _connection_password
        zabbix-admin-password:
            zabbix_user.admin_password_present

        # directly set password
        zabbix-admin-password:
            zabbix_user.admin_password_present:
                - password: SECRET_PASS
    '''
    dry_run = __opts__['test']
    default_zabbix_user = 'Admin'
    default_zabbix_password = 'zabbix'
    ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}

    passwords = []
    connection_args = {}
    connection_args['_connection_user'] = default_zabbix_user
    if '_connection_url' in kwargs:
        connection_args['_connection_url'] = kwargs['_connection_url']

    config_password = __salt__['config.option']('zabbix.password', None)
    if config_password:
        passwords.append(config_password)
    if '_connection_password' in kwargs:
        passwords.append(kwargs['_connection_password'])
    if password:
        passwords.append(password)

    # get unique list in preserved order and reverse it
    seen = set()
    unique_passwords = [six.text_type(x) for x in passwords if x not in seen and not seen.add(x)]
    unique_passwords.reverse()

    if not unique_passwords:
        ret['comment'] = 'Could not find any Zabbix Admin password setting! See documentation.'
        return ret
    else:
        desired_password = unique_passwords[0]

    unique_passwords.append(default_zabbix_password)

    for pwd in unique_passwords:
        connection_args['_connection_password'] = pwd
        try:
            user_get = __salt__['zabbix.user_get'](default_zabbix_user, **connection_args)
        except SaltException as err:
            if 'Login name or password is incorrect' in six.text_type(err):
                user_get = False
            else:
                raise
        if user_get:
            if pwd == desired_password:
                ret['result'] = True
                ret['comment'] = 'Admin password is correct.'
                return ret
            else:
                break

    if user_get:
        if not dry_run:
            user_update = __salt__['zabbix.user_update'](user_get[0]['userid'],
                                                         passwd=desired_password,
                                                         **connection_args)
            if user_update:
                ret['result'] = True
                ret['changes']['passwd'] = 'changed to \'' + six.text_type(desired_password) + '\''
        else:
            ret['result'] = None
            ret['comment'] = 'Password for user ' + six.text_type(default_zabbix_user) \
                             + ' updated to \'' + six.text_type(desired_password) + '\''

    return ret