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

# Copyright 2008-2010 Calculate Ltd. 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 sys
# Ввод pwd
import getpass
import types
from cl_utils import removeDir
from cl_print import color_print
from server.share import servicesAPI
from server.utils import rawInput, isCorrectStringNet, addInfoUser, addInfoGroup, dialogYesNo
# Перевод модуля
import cl_lang
tr = cl_lang.lang()
tr.setLocalDomain('cl_lib')
tr.setLanguage(sys.modules[__name__])
import cl_overriding

class users(color_print):
    """Общие методы для серверных программ,

    (работа с пользователями и группами)"""

    # Объект с методами доступа к другим сервисам
    servicesAPIObj = servicesAPI()

    # Статические группы
    staticGroups = {\
        'client':addInfoGroup('client',
                               '900',
                               'Client group',
                               '2801',
                               '2'),
        'Domain Admins':addInfoGroup('Domain Admins',
                                     '512',
                                     'Domain Administrators',
                                     '512',
                                     '2'),
        'Domain Users':addInfoGroup('Domain Users',
                                    '513',
                                    'Domain Users',
                                    '513',
                                    '2'),
        'Domain Guests':addInfoGroup('Domain Guests',
                                     '514',
                                     'Domain Guests Users',
                                     '514',
                                     '2'),
        'Domain Computers':addInfoGroup('Domain Computers',
                                        '515',
                                        'Domain Computers accounts',
                                        '515',
                                        '2'),
        'Administrators':addInfoGroup('Administrators',
                                      '544',
                                      'Domain Members can fully \
administer the computer/sambaDomainName',
                                      '544',
                                      '5',
                                      "S-1-5-32-544"),
        'Account Operators':addInfoGroup('Account Operators',
                                         '548',
                                         'Domain Users to manipulate \
users accounts',
                                         '548',
                                         '5',
                                         "S-1-5-32-548"),
        'System Operators':addInfoGroup('System Operators',
                                        '549',
                                        'Domain System Operators',
                                        '549',
                                        '5',
                                        "S-1-5-32-549"),
        'Print Operators':addInfoGroup('Print Operators',
                                        '550',
                                        'Domain Print Operators',
                                        '550',
                                        '5',
                                        "S-1-5-32-550"),
        'Backup Operators':addInfoGroup('Backup Operators',
                                        '551',
                                        'Domain Members can bypass \
file security to back up files',
                                        '551',
                                        '5',
                                        "S-1-5-32-551"),
        'Replicators':addInfoGroup('Replicators',
                                   '552',
                                   'Domain Supports file replication \
in a sambaDomainName',
                                    '552',
                                    '5',
                                    "S-1-5-32-552"),
                                          }
    # Статические пользователи
    staticUsers = {\
        'client':addInfoUser('client',
                             '900',
                             '900',
                             'Client samba user'),
        'admin':addInfoUser('admin',
                             '901',
                             '544',
                             'Admin samba user')}

    def getUserUidAndGid(self, userName, groupName=""):
        """Находит в системе uid и gid пользователя

        userName - имя пользователя и имя группы пользователя
        """
        if not groupName:
            groupName = userName
        import pwd
        try:
            uid = pwd.getpwnam(userName)[2]
        except:
            self.printERROR(_("Can not found user %s in this system")%userName)
            return ()
        try:
            import grp
            gid = grp.getgrnam(groupName)[2]
        except:
            self.printERROR(_("Can not found group %s in this system")\
                            %groupName)
            return ()
        return (uid, gid)


    def __restoreDelUser(self,userName,service,srcDir,message,unixObj=False):
        """Возвращаем данные удаленного пользователя"""
        # Ищем Unix пользователя
        searchUnixUser = self.servicesAPIObj.searchUnixUser(userName, unixObj)
        # id пользователя
        strUid = ""
        if searchUnixUser:
            strUid = searchUnixUser[0][0][1]['uidNumber'][0]
        else:
            resPasswd = self.servicesAPIObj.searchPasswdUser(userName, unixObj)
            if resPasswd:
                strUid = resPasswd.split(":")[2]
        if strUid:
            delBackDir =\
                os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%s-%s"%(userName,strUid),
                                             service)
        if strUid and os.path.exists(delBackDir) and os.listdir(delBackDir):
            if message == None or type(message) == types.BooleanType:
                dialogRes = message
            else:
                dialogRes = dialogYesNo(message)
            if dialogRes and dialogRes == True:
                try:
                    copyDir(srcDir, delBackDir)
                except:
                    self.printERROR(_("Not restore user data in dir %s")\
                                    %srcDir)
                    return False
                self.printSUCCESS(_("Restore user data in dir %s")\
                          %srcDir)
                return  "Yes", delBackDir
            elif dialogRes == False:
                return "No", delBackDir
            elif dialogRes == None:
                return "Cancel", delBackDir
        return True

    def restorePathDelUser(self,userName,destDir,relDir,message,unixObj=False):
        """Восстанавливает директорию удаленного пользователя"""
        removedDir = False
        flagError = False
        resRestore = self.__restoreDelUser(userName, relDir,
                                         destDir, message, unixObj)
        # Если ошибка то выходим
        if not resRestore:
            flagError = True
        # Флаг создания директории профиля пользователя
        createDir = destDir
        term = ""
        if resRestore == True:
            term = message
        if not flagError and type(resRestore) == types.TupleType:
            # Если cansel
            if resRestore[0] == "Cancel":
                # Удаляем пользователя
                flagError = True
                term = None
            # Если No
            elif resRestore[0] == "No":
                try:
                    removeDir(resRestore[1])
                except:
                    flagError = True
                if not flagError:
                    removedDir = resRestore[1]
                    term = False
            elif resRestore[0] == "Yes":
                createDir = False
                removedDir = resRestore[1]
                term = True
        if flagError or term == "":
            return False
        else:
            return (term, createDir, removedDir)


    def backupDelUser(self, userName, service, srcDir, unixObj=False):
        """Сохраняем данные удаляемого пользователя"""
        # Ищем Unix пользователя
        searchUnixUser = self.servicesAPIObj.searchUnixUser(userName, unixObj)
        # id пользователя
        strUid = ""
        if searchUnixUser:
            strUid = searchUnixUser[0][0][1]['uidNumber'][0]
        if strUid:
            delBackDir =\
                os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%s-%s"%(userName,strUid),
                                             service)
            if os.path.exists(delBackDir) and os.listdir(delBackDir):
                self.printERROR(_("Found deleted user data dir %s")\
                              %delBackDir)
                self.printERROR(_("Not created deleted user data dir %s")\
                            %delBackDir)
                return False
        else:
            delBackDir =\
                os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%s"%(userName),
                                             service)
            i = 0
            while os.path.exists(delBackDir):
                i += 1
                delBackDir =\
                    os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%s_%s"%(userName,i),
                                             service)
        # Cоздаем директорию хранения удаленных пользователей
        if not os.path.exists(self.clVars.Get("sr_deleted_path")):
            os.makedirs(self.clVars.Get("sr_deleted_path"))
        #Делаем сохранение директории
        try:
            copyDir(delBackDir,srcDir)
        except:
            self.printERROR(_("Can not copy deleted user data in dir %s")\
                            %delBackDir)
            return False
        self.printSUCCESS(_("Created deleted user data dir %s")\
                          %delBackDir)
        return True

    def removeEmptyDir(self, rmDir):
        """Удаление пустых директорий"""
        if not os.path.exists(rmDir):
            self.printERROR(_("Not found remove dir %s") %rmDir)
            return False
        rDir = rmDir
        while os.listdir(rDir) == []:
            os.rmdir(rDir)
            rDir = os.path.split(rDir)[0]
            if rDir == "/":
                break
        return True

    def createUserDir(self, uid, gid, userDir, mode=0700):
        """Создание пользовательской директории"""
        if not os.path.exists(userDir):
            os.makedirs(userDir)
            if mode:
                os.chmod(userDir,mode)
            os.chown(userDir,uid,gid)
            return True
        else:
            self.printERROR(_("Path %s exists") %userDir)
            return False

    def createUserFile(self, fileName, fileTxt, uid, gid, mode=0644):
        """Создает пользовательский файл с содержимым

        Если директория файла не существует то ошибка
        """
        userDir = os.path.split(fileName)[0]
        if not os.path.exists(userDir):
            self.printERROR(_("Path %s not exists") %userDir)
            return False
        fd = os.open(fileName, os.O_CREAT)
        os.close(fd)
        os.chmod(fileName, mode)
        os.chown(fileName,uid,gid)
        if fileTxt:
            FD = open(fileName, "r+")
            FD.write(fileTxt)
            FD.close()
        return True

    def getUserAllowNetwork(self, strPrompt, strNetAllow):
        """Получаем от пользователя доверительные сети

        вывод - список доверительных сетей
        """
        def printW():
            cl_overriding.printSUCCESS(_("Incorrect string allow networks"))
            cl_overriding.printSUCCESS(\
                _("Example - allow networks: 10.0.0.0/24 10.0.10.0/24"))
            cl_overriding.printSUCCESS(_("Try again\n"))
        strNet = rawInput(strPrompt, strNetAllow)
        i = 0
        while i<3 and not isCorrectStringNet(strNet):
            printW()
            strNet = rawInput(strPrompt, strNet)
            i +=1
        if i == 3 and not isCorrectStringNet(strNet):
            printW()
            self.printERROR(_("You used four attempts, \
if you want to continue to run the program again"))
            return False
        return isCorrectStringNet(strNet)
