# -*- coding: utf-8 -*-

# Copyright 2008-2016 Mir Calculate. http://www.calculate-linux.org
#
#  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.

import os
import pwd
import grp
from os import environ, path
from ..datavars import Variable, VariableError, ReadonlyVariable
from ..utils.common import getPasswdUsers, isBootstrapDataOnly
from ..utils.files import listDirectory
import sys
from ..cl_lang import setLocalTranslate

_ = lambda x: x
setLocalTranslate('cl_lib3', sys.modules[__name__])

try:
    from ..cl_ldap import ldapUser, ldap
except ImportError:
    ldapUser = None
    ldap = None


class LdapHelper():
    # data object from LDAP
    _ldapUserObject = False
    # user data from LDAP
    _ldapUserData = {}

    def getUserInfo(self, username):
        """Get information about user from LDAP in dict format"""
        if username:
            if username in LdapHelper._ldapUserData:
                return LdapHelper._ldapUserData[username]
            elif ldapUser is not None:
                ldapObj = self.getLdapUserObject()
                if ldapUser and isinstance(ldapObj, ldapUser):
                    user_info = ldapObj.getUserLdapInfo(username)
                    if user_info:
                        LdapHelper._ldapUserData[username] = user_info
                        return user_info
        return {}

    def getLdapUserObject(self):
        """Get data obejct from LDAP"""
        if not LdapHelper._ldapUserObject and ldapUser:
            LdapHelper._ldapUserObject = ldapUser()
        return LdapHelper._ldapUserObject

    def getLdapUserlist(self):
        """
        Get userlist from LDAP
        """
        user_obj = self.getLdapUserObject()
        if ldapUser and isinstance(user_obj, ldapUser):
            if user_obj.connectLdap():
                return [ x[0][1]['uid'][0].decode("UTF-8") for x in user_obj.ldapObj.ldapSearch(
                               user_obj.getUsersDN(),
                               ldap.SCOPE_ONELEVEL, '(objectClass=*)',
                               ['uid'])]
        return []


class VariableUrLogin(Variable, LdapHelper):
    """
    User Login
    """
    type = "choiceedit"
    opt = ["ur_login"]
    metavalue = "USER"
    untrusted = True

    def init(self):
        self.help = _("username")
        self.label = _("User name")

    def choice(self):
        return [""] + sorted(list(set(
            self.getLdapUserlist() + getPasswdUsers())))

    def check(self, value):
        """Does user exist"""
        if value == "":
            raise VariableError(_("Need to specify user"))
        try:
            pwd.getpwnam(value).pw_gid
        except Exception:
            raise VariableError(_("User %s does not exist") % value)

    def get(self):
        if self.Get('cl_action') == "desktop":
            return ""
        try:
            user = environ['USER']
            pwd.getpwnam(user)
            return user
        except (KeyError, TypeError):
            uid = os.getuid()
            try:
                user_name = pwd.getpwuid(uid).pw_name
            except (KeyError, TypeError):
                return ""
            return user_name


class VariableUrGroup(ReadonlyVariable):
    """
    User group name
    """

    def get(self):
        gid = self.Get('ur_gid')
        try:
            return grp.getgrgid(int(gid)).gr_name
        except (KeyError, TypeError):
            return ""


class VariableUrGid(ReadonlyVariable):
    """
    User GID
    """
    type = "int"

    def get(self):
        user_name = self.Get('ur_login')
        if user_name:
            try:
                return str(pwd.getpwnam(user_name).pw_gid)
            except (KeyError, TypeError):
                return ""
        return ""


class VariableUrUid(ReadonlyVariable):
    """
    User GID
    """
    type = "int"

    def get(self):
        username = self.Get('ur_login')
        if username:
            try:
                return str(pwd.getpwnam(username).pw_uid)
            except (KeyError, TypeError):
                return ""
        else:
            return ""


class VariableUrFullname(ReadonlyVariable):
    """
    User fullname
    """

    def get(self):
        username = self.Get('ur_login')
        fullname = ""
        if username:
            try:
                fullname = pwd.getpwnam(username).pw_gecos
            except (KeyError, TypeError):
                return ""
        return fullname


class VariableUrHomePath(ReadonlyVariable):
    """
    User home directory
    """

    def get(self):
        """Get user home directory"""
        username = self.Get('ur_login')
        homedir = ""
        if username:
            try:
                homedir = pwd.getpwnam(username).pw_dir
            except (KeyError, TypeError):
                return ""
        return homedir


class VariableUrJid(ReadonlyVariable, LdapHelper):
    """
    User Jabber id (Get from LDAP)
    """

    def get(self):
        """Get user Jabber id"""
        userinfo = self.getUserInfo(self.Get('ur_login'))
        userjid = ""
        if userinfo:
            userjid = userinfo["jid"]
        return userjid


class VariableUrMail(ReadonlyVariable, LdapHelper):
    """
    User email (Get from LDAP)
    """

    def get(self):
        userinfo = self.getUserInfo(self.Get('ur_login'))
        usermail = ""
        if userinfo:
            usermail = userinfo["mail"]
        return usermail


class VariableClHomeCryptSet(Variable):
    """
    Вкл/выкл шифрование пользовательских профилей
    """
    value = "off"

    type = "bool"


class VariableUrHomeCryptSet(ReadonlyVariable):
    """
    Шифрованный или нет пользовательский профиль
    """
    type = "bool"

    def get(self):
        # если у пользователский профиль настроен как шифрованный
        login = self.Get('ur_login')
        if login == "root":
            return "off"
        cryptpath = path.join('/home/.ecryptfs', login, '.ecryptfs')
        if path.exists(cryptpath):
            return "on"
        # если пользовательского профиля нет, то шифровать ли профиль
        # узнаем на уровне системы
        homedir = self.Get('ur_home_path')
        if (not path.exists(homedir) or not listDirectory(homedir) or
                isBootstrapDataOnly(homedir)):
            return self.Get('cl_home_crypt_set')
        # профиль не шифрованный
        return "off"
