#!/usr/bin/env python
#-*- encoding: utf-8 -*-
#
# This file belongs to coshsh.
# Copyright Gerhard Lausser.
# This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

import sys
reload(sys)
sys.setdefaultencoding('utf8')

from optparse import OptionParser
import sys
import os
import re
import shutil
from tempfile import gettempdir
from logging import INFO, DEBUG

sys.dont_write_bytecode = True
try:
    import coshsh
except Exception:
    if 'COSHSH_HOME' in os.environ:
        coshsh_home = os.environ['COSHSH_HOME']
    else:
        coshsh_home = os.path.join(os.path.dirname(__file__), '..')
        os.environ['COSHSH_HOME'] = coshsh_home
    sys.path.append(coshsh_home)
    try:
        import coshsh
    except Exception:
        print "Could not load package coshsh. Check your PYTHONPATH"
        sys.exit(3)

from coshsh.generator import Generator
from coshsh.recipe import Recipe
from coshsh.util import substenv
from coshsh.configparser import CoshshConfigParser


class GeneratorMessage(object):
    def __init__(self, message):
        self.message = message

class WarningMessage(GeneratorMessage):
    pass

class CriticalMessage(GeneratorMessage):
    pass

class OkMessage(GeneratorMessage):
    pass


if __name__ == '__main__':
    VERSION = "1.0"


    parser = OptionParser(
        "%prog [options] --cookbook cookbookfile [--recipe recipe]",
        version="%prog " + VERSION)
    parser.add_option('--cookbook', action='store',
                      dest="cookbook_file",
                      help='Config file')
    parser.add_option('--recipe', action='store',
                      dest="default_recipe",
                      help="Cook a configuration following <recipe>")
    parser.add_option('--debug', action='store_const',
                      const="debug",
                      default="info",
                      dest="default_log_level",
                      help="Output additional messages on stdout")
    parser.add_option('--force', action='store_true',
                      default=False,
                      dest="force",
                      help="Force datasource to be read")
    parser.add_option('--safe-output', action='store_true',
                      default=False,
                      dest="safe_output",
                      help="Do not commit when hosts disappeared")

    opts, args = parser.parse_args()
    generator = Generator()
    if opts.cookbook_file:
        recipe_configs = {}
        datasource_configs = {}
        datarecipient_configs = {}
        cookbook = coshsh.configparser.CoshshConfigParser()
        cookbook.read(opts.cookbook_file)
        if cookbook._sections == {}:
            print "Bad or missing cookbook file : %s " % opts.cookbook_file
            sys.exit(2)
            
        for ds in [section for section in cookbook.sections() if section.startswith('datarecipient_')]:
            datarecipient_configs[ds.replace("datarecipient_", "", 1).lower()] = cookbook.items(ds) + [('name', ds.replace("datarecipient_", "", 1).lower())]
        for ds in [section for section in cookbook.sections() if section.startswith('datasource_')]:
            datasource_configs[ds.replace("datasource_", "", 1).lower()] = cookbook.items(ds) + [('name', ds.replace("datasource_", "", 1).lower())]
        for recipe in [section for section in cookbook.sections() if section.startswith('recipe_')]:
            recipe_configs[recipe.replace("recipe_", "", 1).lower()] = cookbook.items(recipe) + [('name', recipe.replace("recipe_", "", 1).lower())]

        recipes = []
        if opts.default_recipe:
            recipes = [r.lower() for r in opts.default_recipe.split(",")]
        else:
            if "defaults" in cookbook.sections() and "recipes" in [c[0] for c in cookbook.items("defaults")]:
                recipes = [recipe.lower() for recipe in dict(cookbook.items("defaults"))["recipes"].split(",")]
            else:
                recipes = recipe_configs.keys()
        if "defaults" in cookbook.sections() and "log_dir" in [c[0] for c in cookbook.items("defaults")]:
            log_dir = dict(cookbook.items("defaults"))["log_dir"]
            log_dir = re.sub('%.*?%', coshsh.util.substenv, log_dir)
        elif 'OMD_ROOT' in os.environ:
            log_dir = os.path.join(os.environ['OMD_ROOT'], "var", "coshsh")
        else:
            log_dir = gettempdir()
        if "defaults" in cookbook.sections() and "pid_dir" in [c[0] for c in cookbook.items("defaults")]:
            pid_dir = dict(cookbook.items("defaults"))["pid_dir"]
            pid_dir = re.sub('%.*?%', coshsh.util.substenv, pid_dir)
        else:
            pid_dir = gettempdir()
        if opts.default_log_level and opts.default_log_level.lower() == "debug" or "defaults" in cookbook.sections() and "log_level" in [c[0] for c in cookbook.items("defaults")] and cookbook.items("defaults")["log_level"].lower() == "debug":
            generator.setup_logging(logdir=log_dir, scrnloglevel=DEBUG)
        else:
            generator.setup_logging(logdir=log_dir, scrnloglevel=INFO)
        for recipe in recipes:
            if recipe in recipe_configs.keys():
                recipe_configs[recipe].append(('force', opts.force))
                recipe_configs[recipe].append(('safe_output', opts.safe_output))
                if not [c for c in recipe_configs[recipe] if c[0] == 'pid_dir']:
                    recipe_configs[recipe].append(('pid_dir', pid_dir))
                generator.add_recipe(**dict(recipe_configs[recipe]))
                if recipe not in generator.recipes:
                    # something went wrong in add_recipe. we should already see
                    # an error message here.
                    continue
                for ds in generator.recipes[recipe].datasource_names:
                    if ds in datasource_configs.keys():
                        generator.recipes[recipe].add_datasource(**dict(datasource_configs[ds]))
                    else:
                        parser.error("Datasource %s is unknown" % ds)
                for dr in generator.recipes[recipe].datarecipient_names:
                    if dr == "datarecipient_coshsh_default":
                        # implicitely added by recipe.__init__
                        pass
                    elif dr in datarecipient_configs.keys():
                        generator.recipes[recipe].add_datarecipient(**dict(datarecipient_configs[dr]))
                    else:
                        parser.error("Datarecipient %s is unknown" % dr)
            else:
                parser.error("Recipe %s is unknown" % recipe)
    else:
        parser.error("Use option -c/--cookbook")
    if args:
        parser.error("Does not accept any argument. Use option -c/--cookbook")
    #if len(generator.datasources) == 0:
    #   parser.error("None of the cookbookured datasources was found")

    # nagios_dir cookbook option sets an alternative target
    # and may be used to replace Coshsh.base_dir
    generator.run()

