#!/usr/bin/env python

import os
import stat
from ansible.module_utils.basic import * # noqa

DOCUMENTATION = '''
---
module: scan_files
short_description: Return file state information as fact data for a directory tree
description:
     - Return file state information recursively for a directory tree on the filesystem
version_added: "1.9"
options:
  path:
    description: The path containing files to be analyzed
    required: true
    default: null
  recursive:
    description: scan this directory and all subdirectories
    required: false
    default: no
  get_checksum:
    description: Checksum files that you can access
    required: false
    default: false
requirements: [ ]
author: Matthew Jones
'''

EXAMPLES = '''
# Example fact output:
# host | success >> {
#     "ansible_facts": {
#         "files": [
#             {
#                 "atime": 1427313854.0755742,
#                 "checksum": "cf7566e6149ad9af91e7589e0ea096a08de9c1e5",
#                 "ctime": 1427129299.22948,
#                 "dev": 51713,
#                 "gid": 0,
#                 "inode": 149601,
#                 "isblk": false,
#                 "ischr": false,
#                 "isdir": false,
#                 "isfifo": false,
#                 "isgid": false,
#                 "islnk": false,
#                 "isreg": true,
#                 "issock": false,
#                 "isuid": false,
#                 "mode": "0644",
#                 "mtime": 1427112663.0321455,
#                 "nlink": 1,
#                 "path": "/var/log/dmesg.1.gz",
#                 "rgrp": true,
#                 "roth": true,
#                 "rusr": true,
#                 "size": 28,
#                 "uid": 0,
#                 "wgrp": false,
#                 "woth": false,
#                 "wusr": true,
#                 "xgrp": false,
#                 "xoth": false,
#                 "xusr": false
#             },
#             {
#                 "atime": 1427314385.1155744,
#                 "checksum": "16fac7be61a6e4591a33ef4b729c5c3302307523",
#                 "ctime": 1427384148.5755742,
#                 "dev": 51713,
#                 "gid": 43,
#                 "inode": 149564,
#                 "isblk": false,
#                 "ischr": false,
#                 "isdir": false,
#                 "isfifo": false,
#                 "isgid": false,
#                 "islnk": false,
#                 "isreg": true,
#                 "issock": false,
#                 "isuid": false,
#                 "mode": "0664",
#                 "mtime": 1427384148.5755742,
#                 "nlink": 1,
#                 "path": "/var/log/wtmp",
#                 "rgrp": true,
#                 "roth": true,
#                 "rusr": true,
#                 "size": 48768,
#                 "uid": 0,
#                 "wgrp": true,
#                 "woth": false,
#                 "wusr": true,
#                 "xgrp": false,
#                 "xoth": false,
#                 "xusr": false
#             },
'''


def main():
    module = AnsibleModule(
        argument_spec = dict(paths=dict(required=True, type='list'),
                             recursive=dict(required=False, default='no', type='bool'),
                             get_checksum=dict(required=False, default='no', type='bool')))
    files = []
    paths = module.params.get('paths')
    for path in paths:
        path = os.path.expanduser(path)
        if not os.path.exists(path) or not os.path.isdir(path):
            module.fail_json(msg = "Given path must exist and be a directory")

        get_checksum = module.params.get('get_checksum')
        should_recurse = module.params.get('recursive')
        if not should_recurse:
            path_list = [os.path.join(path, subpath) for subpath in os.listdir(path)]
        else:
            path_list = [os.path.join(w_path, f) for w_path, w_names, w_file in os.walk(path) for f in w_file]
        for filepath in path_list:
            try:
                st = os.stat(filepath)
            except OSError:
                continue

            mode = st.st_mode
            d = {
                'path'     : filepath,
                'mode'     : "%04o" % stat.S_IMODE(mode),
                'isdir'    : stat.S_ISDIR(mode),
                'ischr'    : stat.S_ISCHR(mode),
                'isblk'    : stat.S_ISBLK(mode),
                'isreg'    : stat.S_ISREG(mode),
                'isfifo'   : stat.S_ISFIFO(mode),
                'islnk'    : stat.S_ISLNK(mode),
                'issock'   : stat.S_ISSOCK(mode),
                'uid'      : st.st_uid,
                'gid'      : st.st_gid,
                'size'     : st.st_size,
                'inode'    : st.st_ino,
                'dev'      : st.st_dev,
                'nlink'    : st.st_nlink,
                'atime'    : st.st_atime,
                'mtime'    : st.st_mtime,
                'ctime'    : st.st_ctime,
                'wusr'     : bool(mode & stat.S_IWUSR),
                'rusr'     : bool(mode & stat.S_IRUSR),
                'xusr'     : bool(mode & stat.S_IXUSR),
                'wgrp'     : bool(mode & stat.S_IWGRP),
                'rgrp'     : bool(mode & stat.S_IRGRP),
                'xgrp'     : bool(mode & stat.S_IXGRP),
                'woth'     : bool(mode & stat.S_IWOTH),
                'roth'     : bool(mode & stat.S_IROTH),
                'xoth'     : bool(mode & stat.S_IXOTH),
                'isuid'    : bool(mode & stat.S_ISUID),
                'isgid'    : bool(mode & stat.S_ISGID),
            }
            if get_checksum and stat.S_ISREG(mode) and os.access(filepath, os.R_OK):
                d['checksum'] = module.sha1(filepath)
            files.append(d)
    results = dict(ansible_facts=dict(files=files))
    module.exit_json(**results)


main()
