import os
import collections.abc

import click
import yaml


def cleanup(data):
    if isinstance(data, dict):
        return cleanup_dict(data)
    elif isinstance(data, list):
        return [cleanup(item) for item in data]
    else:
        return data


def cleanup_dict(data):
    """remove all keys with value None
    """
    result = {}
    for key, value in data.items():
        if value is None:
            continue

        elif isinstance(value, dict):
            result[key] = cleanup_dict(value)

        else:
            result[key] = cleanup(value)

    return result


def definition_to_string(k8s_obj) -> str:
    if hasattr(k8s_obj, "dict"):
        k8s_dict = k8s_obj.dict(by_alias=True)
    elif isinstance(k8s_obj, dict):
        k8s_dict = k8s_obj
    else:
        raise AttributeError("cannot handle k8s_obj " + repr(k8s_obj))

    k8s_def = cleanup_dict(k8s_dict)
    return yaml.safe_dump(k8s_def)


def chart_to_string(chart) -> str:
    return "---\n".join(map(definition_to_string, chart))


def synth(chart_variables: dict, output_format: str, output: str) -> int:
    if not "chart" in chart_variables:
        click.secho(f'{input} did not define a variable: "chart"', fg="red", bold=True)
        return 1
    
    chart = chart_variables["chart"]

    if not isinstance(chart, collections.abc.Iterable):
        click.secho(f'{input}:chart must be iterable, e.g. a list or k8s.Chart', fg="red", bold=True)
        return 2

    if not os.path.exists(output):
        os.makedirs(output)

    chart_text = chart_to_string(chart)
    header = "# This file is generated by pdk8s, editing is strongly discouraged\n"
    description = chart_variables.get("__doc__", "")
    description = description.strip()

    if output_format == "helm":
        helm_chart = {
            "apiVersion": "v2",
            "name": chart_variables["name"],
            "description": description,
            "type": "application",
            "version": chart_variables["chart_version"],
            "appVersion": chart_variables["app_version"]
        }

        with open(os.path.join(output, "Chart.yaml"), "w") as f:
            f.write(header)
            f.write(yaml.safe_dump(helm_chart))

        with open(os.path.join(output, "values.yaml"), "w") as f:
            f.write(header)
            f.write("# This helm chart does not support values via helm.")
            f.write("# To parameterize it, use the pdk8s source of this chart")

        templates_path = os.path.join(output, "templates")
        if not os.path.exists(templates_path):
            os.makedirs(templates_path)

        with open(os.path.join(templates_path, "generated.yaml"), "w") as f:
            f.write(header)
            f.write(chart_text)

    elif output_format == "kubernetes":
        with open(os.path.join(output, "chart.yaml")) as f:
            f.write(header)
            for line in description.split('\n'):
                f.write(f'# {line}\n')
            f.write(chart_text)

    else:
        raise NotImplementedError()

    return 0
