#!/usr/bin/env python

# Copyright 2012-2013, Gautam R Singh
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# -------------------------------------------------------------------- #
# 01.01.2014 - release to github - g@ut.am
# -------------------------------------------------------------------- #

from __future__ import print_function
import os
import platform
import time
import logging
import inspect
import argparse
import re
import sys

DEBUG = False
# -------------------------------------------------------------------- #
# for hacky tests
if os.path.basename(__file__) == 'test_sillyfacter':
    sys.path = [sys.path[0],
                os.path.dirname(os.path.abspath(__file__))] + sys.path
    DEBUG = True
# -------------------------------------------------------------------- #

import sillyfacter.config


VERSION = sillyfacter.config.VERSION
MODULEFILE = re.sub('\.py', '',
                            os.path.basename(inspect.stack()[0][1]))
MODULES = ["process", "network", "user", "os", "filesystem"]

# -------------------------------------------------------------------- #
# for debug:
def enable_debug():
    global VERSION
    global DEBUG
    VERSION += \
        '-test-{}'.format(int(time.time()))
    DEBUG = True
    sillyfacter.config.VERSION = VERSION
    sillyfacter.config.DEBUG = DEBUG
    sillyfacter.config.STRICT = False
    print("-"*79)
    print(" sys.path : {}".format(sys.path))
    print(" version  : {}".format(VERSION))
    print(" debug    : {}".format(DEBUG))
    print("-"*79)
# -------------------------------------------------------------------- #


if __name__ == '__main__':
    hostname = platform.node().split(".")[0]
    scan_time = int(time.time())
    parser = argparse.ArgumentParser(
        description='Sillyfacter fetches facts about the state of the ' +
                    'system. Gathers process, open file, socket info ' +
                    'and then outputs a JSON (currently). Designed for ' +
                    'dependency mappings.')
    parser.add_argument('--modules', type=str,
                        help='comma seperated list of modules ' +
                             'to be executed. Default list is ' +
                             '"all" which is expanded to include ' +
                             '"{}"'.format(",".join(MODULES)),
                        default="process,user,network,os,filesystem,ansible")
    parser.add_argument('--out', type=str,
                        help='URL for the backend Mongo database ' +
                             '(E.g. mongodb://localhost:27017/). '
                             'If nothing is supplied it dumps JSON to stdout',
                        default=None)
    parser.add_argument('--log', type=str,
                        help='file to write logs to, otherwise logs are ' +
                        'written to console',
                        default=None)
    parser.add_argument('--verbose', '-v', action='count',
                        help='Use multiple "-v" options',
                        default=0)
    parser.add_argument('--strict',
                        help='If selected will error out on every exeption ' +
                             'Note: Useful when debugging only [False]',
                             default=False,
                             action='store_true')
    parser.add_argument('--debug',
                        help='If selected will emit very debugging logs if ' +
                             'exception are encountered. ' +
                             'Note: Useful when debugging only [False]',
                             default=False,
                             action='store_true')
    parser.add_argument('--scan',
                        choices=('auto', 'new', 'last'),
                        help='[NOT IMPLEMENTED] ' +
                             'choose the scan type, usually "auto" ' +
                             'is the best.  [auto]', default='auto')
    parser.add_argument('--raw',
                        help='[NOT IMPLEMENTED] ' +
                             'Use raw output, default is false',
                        action='store_true')
    parser.add_argument('--version', action='version',
                        version=VERSION)

    args = parser.parse_args()
    if args.debug:
        enable_debug()
    sillyfacter.config.STRICT = args.strict
    #
    import sillyfacter.common
    #
    lg = sillyfacter.common.setup_logger(level=args.verbose,
                                         logfile=args.log)
    ldict = {"step": "main",
             "hostname": platform.node().split(".")[0]}
    l = logging.LoggerAdapter(sillyfacter.common.fetch_lg(), ldict)
    l.info("Starting {} v{}".format(__file__, VERSION))
    if sillyfacter.config.STRICT is True:
        l.warning("Strict mode is enabled!!")
    #
    fetchable = {}
    modules = []
    try:
        for m in args.modules.split(','):
            if re.match("all", m, re.IGNORECASE):
                modules += MODULES
            else:
                modules.append(m)
    except:
        modules = MODULES
    finally:
        modules = list(set(modules))

    #
    retval = 0
    #
    if args.out is None or \
            re.match('^[/a-z0-9].*\.json', args.out, re.IGNORECASE):
        outmodule = "json"
        output = None
        try:
            l.info("Importing output filter '{}'".format(outmodule))
            outmodule = __import__("sillyfacter.output.{}".format(outmodule),
                                   fromlist=[outmodule])
            output, retval = getattr(outmodule, "output")(modules,
                                                          args.out)
        except:
            raise
        else:
            print(output)
    elif re.match('^mongodb\://.*', args.out):
        outmodule = "mongo"
        output = None
        try:
            l.info("Importing output filter '{}'".format(outmodule))
            outmodule = __import__("sillyfacter.output.{}".format(outmodule),
                                   fromlist=[outmodule])
            output, retval = getattr(outmodule, "output")(modules,
                                                          args.out)
        except:
            raise
        else:
            print(output)
    else:
        print("Invalid argument '{}' passed".format(args.out))
        retval = 1
    l.info("exit code is {}".format(retval))
    sys.exit(retval)
