#!/usr/bin/python3
##############################################################################
# Copyright (c) Members of the EGEE Collaboration. 2010.
# See http://www.eu-egee.org/partners/ for details on the copyright
# holders.
# Copyright (c) Contributors, see list at
#    https://github.com/EGI-Federation/glite-info-static/graphs/contributors
#
# 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.
##############################################################################
#
# NAME :        glite-info-create
#
# DESCRIPTION : This script helps you create LDIF files.
#
# AUTHORS :     David.Horat@cern.ch
#               Laurence.Field@cern.ch
#
# WEB:          https://github.com/EGI-Federation/glite-info-static
#
##############################################################################

import argparse
import logging
import os
import sys
import textwrap

LOG = logging.getLogger("%s" % (sys.argv[0]))


def parse_options():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent(
            """
               Examples:
                 glite-info-static -m site
                 glite-info-static -m site -i 'glue wlcg' -t glue2 -c /etc/site.cfg

               Web site: http://cern.ch/gridinfo
            """
        ),
    )
    parser.add_argument(
        "-d",
        "--debug",
        type=int,
        choices=[0, 1, 2, 3],
        help="Debug level: 0:ERROR (default), 1:WARNING, 2:INFO, 3:DEBUG",
        default=0,
    )
    parser.add_argument(
        "-m", "--module", required=True, help="The module you are using. E.g.: site"
    )
    parser.add_argument(
        "-i",
        "--ifaces",
        nargs="+",
        help="The interface you want to use. E.g.: glue, wlcg (default)",
        default=["glue", "wlcg"],
    )
    parser.add_argument(
        "-t",
        "--templates",
        nargs="+",
        help="The template you want to use. E.g.: glue1, glue2 (all default)",
        default=["glue1", "glue2"],
    )
    parser.add_argument(
        "-c",
        "--configs",
        required=True,
        help="The config file location if outside from the module directory",
    )
    parser.add_argument(
        "-p",
        "--path",
        help="The path for the module directory. Default: /etc/glite-info-static",
        default="/etc/glite-info-static",
    )
    args = parser.parse_args()
    config = {
        "debug": args.debug,
        "path": args.path,
        "ifaces": args.ifaces,
        "templates": args.templates,
        "config": args.configs,
        "module": args.module,
    }
    return config


def main(config):
    module = config["module"]

    # Get key-values from the configuration file.
    config_file = "%s/%s/%s" % (config["path"], module, config["config"])
    if not os.path.exists(config_file):
        LOG.error("Config file %s does not exist." % (config_file))
        sys.exit(1)
    parameters = {}
    for line in open(config_file).readlines():
        index = line.find("=")
        if index > 0:
            key = line[:index].strip()
            value = line[index + 1 :].strip()
            if key not in parameters:
                parameters[key] = []
            parameters[key].append(value)

    # Get the mandatory and optional attributes from the interface file.
    for interface in config["ifaces"]:
        interface_file = "%s/%s/%s.%s.ifc" % (config["path"], module, module, interface)
        if not os.path.exists(interface_file):
            LOG.error("Interface file %s does not exist." % (interface_file))
            sys.exit(1)
        interface_parameters = {}
        for line in open(interface_file).readlines():
            index = line.find("=")
            if index > 0:
                key = line[:index].strip()
                value = line[index + 1 :].strip()
                if not value == "":
                    values = value.split(" ")
                else:
                    values = []
                if key not in interface_parameters:
                    interface_parameters[key] = []
                interface_parameters[key].extend(values)

    # Check the configuration file for the mandatory and optional attributes.
    mandatory_attributes = []
    mandatory_attributes.extend(interface_parameters["MANDATORY_SINGLEVALUED_VARS"])
    mandatory_attributes.extend(interface_parameters["MANDATORY_MULTIVALUED_VARS"])
    for key in mandatory_attributes:
        if key in parameters:
            for value in parameters[key]:
                if value == "":
                    LOG.error("Mandatory atribute %s does not have a value." % (key))
                    sys.exit(1)
        else:
            LOG.error(
                "Mandatory attribute %s is not specified in the configuration file"
                % (key)
            )
            sys.exit(1)

    optional_attributes = []
    optional_attributes.extend(interface_parameters["OPTIONAL_SINGLEVALUED_VARS"])

    optional_attributes.extend(interface_parameters["OPTIONAL_MULTIVALUED_VARS"])

    for key in optional_attributes:
        if key in parameters:
            for value in parameters[key]:
                if value == "":
                    LOG.error("Optional atribute %s does not have a value." % (key))
                    sys.exit(1)

    # Check that single valued attributes are really single
    singlevalued_attributes = []
    singlevalued_attributes.extend(interface_parameters["MANDATORY_SINGLEVALUED_VARS"])
    singlevalued_attributes.extend(interface_parameters["OPTIONAL_SINGLEVALUED_VARS"])
    for key in singlevalued_attributes:
        if key in parameters:
            if len(parameters[key]) > 1:
                LOG.error("Single valued atribute %s has more than one value." % (key))
                sys.exit(1)

    ldif = ""

    # Get the default ldif from the template.
    for template in config["templates"]:
        template_file = "%s/%s/%s.%s.tpl" % (config["path"], module, module, template)
        if not os.path.exists(template_file):
            LOG.error("Template file %s does not exist." % (template_file))
            sys.exit(1)

        ldif = open(template_file).read()

    multivalued_attributes = []
    multivalued_attributes.extend(interface_parameters["MANDATORY_MULTIVALUED_VARS"])
    multivalued_attributes.extend(interface_parameters["OPTIONAL_MULTIVALUED_VARS"])

    # Do the substitution for single valued attributes
    for attribute in singlevalued_attributes:
        # If there is no value then delete the line, otherwise substitute it.
        if attribute in parameters:
            for value in parameters[attribute]:
                if not parameters[attribute] == "":
                    ldif = ldif.replace("$" + attribute, value)
            else:
                ldif = ldif.replace("$" + attribute, "")
        else:
            ldif = ldif.replace("$" + attribute, "")

    # Do the substitution for multivalued attributes
    for attribute in multivalued_attributes:
        # If there is no value then delete the line, otherwise substitute it.
        if attribute in parameters:
            end = ldif.find("$" + attribute)
            start = ldif[:end].rfind("\n") + 1
            glue_attribute = ldif[start:end]
            chunk = ""
            for value in parameters[attribute]:
                if not parameters[attribute] == "":
                    chunk += glue_attribute + value + "\n"
            ldif = ldif.replace(glue_attribute + "$" + attribute, chunk[:-1])
        else:
            ldif = ldif.replace("$" + attribute, "")

    print(ldif)


if __name__ == "__main__":
    config = parse_options()
    hdlr = logging.StreamHandler(sys.stderr)
    formatter = logging.Formatter("[%(levelname)s]: %(message)s")
    hdlr.setFormatter(formatter)
    LOG.addHandler(hdlr)
    LOG.setLevel(config["debug"])
    main(config)
