#!/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 ConfigParser
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


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 = ConfigParser.ConfigParser()
        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()

