#!/usr/bin/env python3

import sys
import json
import yaml
import requests
import textwrap
import io
import gzip
import base64

config_file = sys.argv[1]
configmap_file = sys.argv[2]


def traverse_json(obj):
    if isinstance(obj, dict):
        for k, v in obj.items():
            # CloudBender::StackRef
            if k == "datasource" and v:
                obj[k] = "Prometheus"

            if isinstance(v, dict) or isinstance(v, list):
                traverse_json(v)

    elif isinstance(obj, list):
        for k in obj:
            if isinstance(k, dict) or isinstance(k, list):
                traverse_json(k)


# read config file
with open(config_file, "r") as yaml_contents:
    config = yaml.safe_load(yaml_contents.read())


configmap = ""
if "condition" in config:
    # use index function to make go template happy if '-' in names
    if "-" in config["condition"] and "index" not in config["condition"]:
        tokens = config["condition"].split(".")
        configmap = """{{- if index .Values %(condition)s }}
""" % {
            "condition": " ".join(f'"{w}"' for w in tokens[2:])
        }

    else:
        configmap = (
            """{{- if %(condition)s }}
"""
            % config
        )

# Base configmap for KubeZero
configmap += (
    """apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ printf "%%s-%%s" (include "kubezero-lib.fullname" $) "%(configmap)s" | trunc 63 | trimSuffix "-" }}
  namespace: {{ .Release.Namespace }}
  labels:
    grafana_dashboard: "1"
    {{- include "kubezero-lib.labels" . | nindent 4 }}
"""
    % config
)

# Put all dashboards into a folder ?
if "folder" in config:
    configmap += (
        """  annotations:
    k8s-sidecar-target-directory: %(folder)s
"""
        % config
    )

# compress ?
if "gzip" in config and config["gzip"]:
    configmap += """binaryData:
"""
else:
    configmap += """data:
"""

for b in config["dashboards"]:
    if not b["url"].startswith("file://"):
        response = requests.get(b["url"])
        if response.status_code != 200:
            print(
                "Skipping the file, response code %s not equals 200"
                % response.status_code
            )
            continue
        raw_text = response.text
    else:
        with open(b["url"].replace("file://", ""), "r") as file_contents:
            raw_text = file_contents.read()

    obj = json.loads(raw_text)

    # replace datasources
    traverse_json(obj)

    # Set default tim in all charts to 1h
    obj["time"] = {"from": "now-1h", "to": "now"}
    obj["refresh"] = "30s"

    # set tags
    if "tags" in b:
        obj["tags"] = b["tags"]

    text = json.dumps(obj, indent=2)

    if "gzip" in config and config["gzip"]:
        # compress and base64 encode
        buf = io.BytesIO()
        f = gzip.GzipFile(mode="w", fileobj=buf, mtime=0)
        f.write(text.encode())
        f.close()

        textb64 = base64.b64encode(buf.getvalue()).decode("utf-8")
        textb64 = textwrap.indent(textb64, " " * 4)
        configmap += (
            """  %(name)s.json.gz:
"""
            % b
        )
        configmap += textb64 + "\n"
    else:
        # encode otherwise helm will mess with raw json
        text = (
            text.replace("{{", "{{`{{")
            .replace("}}", "}}`}}")
            .replace("{{`{{", "{{`{{`}}")
            .replace("}}`}}", "{{`}}`}}")
        )
        text = textwrap.indent(text, " " * 4)
        configmap += (
            """  %(name)s.json:
"""
            % b
        )
        configmap += text + "\n"


if "condition" in config:
    configmap += "{{- end }}" + "\n"

# Write Configmap
with open(configmap_file, "w") as f:
    f.write(configmap)
