# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals


class EnvironmentVariable(object):
    __slots__ = ('name',)
    TYPE = None

    def __init__(self, name, **kwargs):
        self.name = name

    def dict(self):
        return {
            'name': self.name,
            'valueFrom': {
                'type': self.TYPE,
                'vaultSecretEnv': {
                    'field': '',
                    'vaultSecret': {
                        'secretVer': '',
                        'secretId': '',
                        'delegationToken': '',
                        'secretName': ''
                    }
                },
                'secretEnv': {
                    'field': '',
                    'keychainSecret': {
                        'keychainId': '',
                        'secretId': '',
                        'secretRevisionId': ''
                    },
                    'secretName': ''
                },
                'literalEnv': {
                    'value': ''
                }
            }
        }

    def __hash__(self):
        return hash((self.name, self.TYPE))


class LiteralEnv(EnvironmentVariable):
    __slots__ = ('value', )
    TYPE = 'LITERAL_ENV'

    def __init__(self, name, value):
        super(LiteralEnv, self).__init__(name=name)
        self.value = value

    def __repr__(self):
        return 'LiteralEnv({}, {})'.format(self.name, self.value)

    def dict(self):
        base_dict = super(LiteralEnv, self).dict()
        base_dict['valueFrom']['literalEnv'] = {'value': self.value}
        return base_dict

    def __eq__(self, other):
        if isinstance(other, LiteralEnv):
            return self.name == other.name and self.value == other.value
        else:
            return False

    def __ne__(self, other):
        return not self == other


class VaultSecretEnv(EnvironmentVariable):
    __slots__ = ('secretId', 'secretVer', 'delegationToken', 'secretName', 'field')
    TYPE = 'VAULT_SECRET_ENV'

    def __init__(self, name, secretId, secretVer=None, delegationToken=None, secretName=None, field=None):
        super(VaultSecretEnv, self).__init__(name=name)
        self.secretId = secretId
        self.secretVer = secretVer
        self.delegationToken = delegationToken
        self.secretName = secretName or ''
        self.field = field or ''

    def __str__(self):
        return 'VaultSecretEnv({}, secretName={})'.format(self.name, self.secretName)

    def __repr__(self):
        return 'VaultSecretEnv({}, {}, secretName={})'.format(self.name, self.secretId, self.secretName)

    def dict(self):
        base_dict = super(VaultSecretEnv, self).dict()
        base_dict['valueFrom']['vaultSecretEnv'] = {
            'field': self.field,
            'vaultSecret': {
                'secretVer': self.secretVer,
                'secretId': self.secretId,
                'delegationToken': self.delegationToken,
                'secretName': self.secretName
            }
        }
        return base_dict

    def __eq__(self, other):
        if isinstance(other, VaultSecretEnv):
            return self.name == other.name and self.secretId == other.secretId
        else:
            return False

    def __ne__(self, other):
        return not self == other


class SecretEnv(EnvironmentVariable):
    __slots__ = ('keychainId', 'secretId', 'secretRevisionId', 'secretName', 'field')
    TYPE = 'SECRET_ENV'

    def __init__(self, name, keychainId, secretId, secretRevisionId, secretName=None, field=None):
        super(SecretEnv, self).__init__(name=name)
        self.keychainId = keychainId
        self.secretId = secretId
        self.secretRevisionId = secretRevisionId
        self.secretName = secretName or ''
        self.field = field or ''

    def __str__(self):
        return 'SecretEnv({}, secretName={})'.format(self.name, self.secretName)

    def __repr__(self):
        return 'SecretEnv({}, {}, {}, {}, secretName={})'.format(
            self.name, self.keychainId, self.secretId, self.secretRevisionId, self.secretName
        )

    def dict(self):
        base_dict = super(SecretEnv, self).dict()
        base_dict['valueFrom']['secretEnv'] = {
            'field': self.field,
            'keychainSecret': {
                'keychainId': self.keychainId,
                'secretId': self.secretId,
                'secretRevisionId': self.secretRevisionId
            },
            'secretName': self.secretName
        }
        return base_dict


ENV_TYPES = (SecretEnv, VaultSecretEnv, LiteralEnv)
TYPE_MAPPING = {t.TYPE: t for t in ENV_TYPES}


def from_nanny_dict(d):
    volume_type_str = d.get('valueFrom', {}).get('type', None)
    if volume_type_str not in TYPE_MAPPING:
        raise ValueError('Invalid instance_spec.containers.env.type {}'.format(volume_type_str))
    else:
        name = d['name']
        value = d['valueFrom']
        if volume_type_str == LiteralEnv.TYPE:
            return LiteralEnv(name, value['literalEnv']['value'])
        elif volume_type_str == SecretEnv.TYPE:
            secret = value['secretEnv']
            return SecretEnv(name, secretName=secret.get('secretName'), field=secret.get('field'), **secret['keychainSecret'])
        elif volume_type_str == VaultSecretEnv.TYPE:
            secret = value['vaultSecretEnv']
            return VaultSecretEnv(name, field=secret.get('field'), **secret['vaultSecret'])
        else:
            raise ValueError('Invalid instance_spec.containers.env.type {}'.format(volume_type_str))
