# -*- coding: utf-8 -*-
import json
import os.path

from chaoslib.exceptions import ActivityFailed
from chaoslib.types import Secrets
from kubernetes import client
from kubernetes.client.rest import ApiException
from logzero import logger
import yaml

from chaosk8s import create_k8s_api_client

__all__ = ["create_statefulset", "scale_statefulset", "remove_statefulset"]


def create_statefulset(spec_path: str, ns: str = "default",
                       secrets: Secrets = None):
    """
    Create a statefulset described by the service config, which must be
    the path to the JSON or YAML representation of the statefulset.
    """
    api = create_k8s_api_client(secrets)

    with open(spec_path) as f:
        p, ext = os.path.splitext(spec_path)
        if ext == '.json':
            statefulset = json.loads(f.read())
        elif ext in ['.yml', '.yaml']:
            statefulset = yaml.safe_load(f.read())
        else:
            raise ActivityFailed(
                "cannot process {path}".format(path=spec_path))

    v1 = client.AppsV1Api(api)
    v1.create_namespaced_stateful_set(ns, body=statefulset)


def scale_statefulset(name: str, replicas: int, ns: str = "default",
                      secrets: Secrets = None):
    """
    Scale a stateful set up or down. The `name` is the name of the stateful
    set.
    """
    api = create_k8s_api_client(secrets)

    v1 = client.AppsV1Api(api)
    body = {"spec": {"replicas": replicas}}
    try:
        v1.patch_namespaced_stateful_set(name, namespace=ns, body=body)
    except ApiException as e:
        raise ActivityFailed(
            "failed to scale '{s}' to {r} replicas: {e}".format(
                s=name, r=replicas, e=str(e)))


def remove_statefulset(name: str = None, ns: str = "default",
                       label_selector: str = None, secrets: Secrets = None):
    """
    Remove a statefulset by `name` in the namespace `ns`.

    The statefulset is removed by deleting it without
        a graceful period to trigger an abrupt termination.

    The selected resources are matched by the given `label_selector`.
    """
    field_selector = "metadata.name={name}".format(name=name)
    api = create_k8s_api_client(secrets)

    v1 = client.AppsV1Api(api)
    if label_selector:
        ret = v1.list_namespaced_stateful_set(
            ns, field_selector=field_selector,
            label_selector=label_selector)
    else:
        ret = v1.list_namespaced_stateful_set(ns,
                                              field_selector=field_selector)

    logger.debug("Found {d} statefulset(s) named '{n}' in ns '{s}'".format(
        d=len(ret.items), n=name, s=ns))

    body = client.V1DeleteOptions()
    for d in ret.items:
        res = v1.delete_namespaced_stateful_set(
            d.metadata.name, ns, body=body)