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

# Copyright 2011-2013 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.

from calculate.lib.datavars import Variable,ReadonlyVariable,VariableError
import os, glob, sys
from os import path

try:
    import OpenSSL
except:
    OpenSSL = None

from calculate.lib.cl_lang import setLocalTranslate
from calculate.lib.utils.files import readLinesFile,pathJoin, listDirectory
from calculate.core.server.decorators import Dec
from calculate.core.server.func import uniq
#from calculate.api.cert_cmd import find_id_cert
setLocalTranslate('cl_core3',sys.modules[__name__])

class VariableClListCertId(ReadonlyVariable):

    def get(self):
        cert_dir =  self.Get('cl_core_client_certs_path')
        return map(lambda x:x[:-4],
               filter(lambda x:x.endswith('.crt'),
               listDirectory(cert_dir)))

class VariableClCertId(Variable):
    """
    Certificate Identification
    """
    type = "choice"
    opt = ["-c"]
    metavalue = "CERT_ID"

    def init(self):
        self.help = _("Certificate identifier")
        self.label = _("Certificate identifier")

    def choice(self):
        return self.Get('cl_list_cert_id')

    def check(self, cert_id):
#        if cert_id != 'all':
        try:
            int(cert_id)
        except ValueError:
            raise VariableError(_("The certificate ID must be int"))
        
        list_certs_id = self.Get('cl_list_cert_id')
        if not cert_id in list_certs_id:
            raise VariableError(_("The certificate with ID %s not exists") \
                                %cert_id)

class VariableClCertPerms(Variable):
    """
    Certificate Permissions
    """
    type = "choice-list"
    opt = ["--cert-perm"]
    metavalue = "perm[,perm2[..]]"

    def init(self):
        self.help = _("Certificate permissions")
        self.label = _("Certificate permissions")

    def choice(self):
        right_list = []
        for key in Dec.rightsMethods.keys():
            right_list += Dec.rightsMethods[key]

        uniq_right_list = uniq(right_list)
        uniq_right_list.sort()
        return uniq_right_list

    def get(self):
        cert_id = self.Get('cl_cert_id')
        groups_list = self.Get('cl_cert_groups')

        group_rights = self.Get('cl_core_group_rights_path')
        rights = self.Get('cl_core_rights')
        # if group = all and not redefined group all
        if 'all' in groups_list:
            find_flag = False
            fd = open(group_rights, 'r')
            t = fd.read()
            # find all in group_rights file
            for line in t.splitlines():
                if not line:
                    continue
                if line.split()[0] == 'all':
                    find_flag = True
                    break
            if not find_flag:
                right_list = []
                for key in Dec.rightsMethods.keys():
                    right_list += Dec.rightsMethods[key]
        
                uniq_right_list = uniq(right_list)
                uniq_right_list.sort()
                return uniq_right_list
#                self.printSUCCESS(_("Certificate %d can call all "
#                                    "methods!")%cert_id)

        else:
            results = []
            if not os.path.exists (group_rights):
                open(group_rights, 'w')
            with open(group_rights) as fd:
                t = fd.read()
                for line in t.splitlines():
                    if not line:
                        continue
                    words = line.split(' ',1)
                    # first word in line equal name input method
                    if words[0] in groups_list:
                        methods = words[1].split(',')
                        for i in methods:
                            results.append(i.strip())

            results = uniq(results)

            add_list_rights = []
            del_list_rights = []

            with open(rights) as fr:
                t = fr.read()
                for line in t.splitlines():
                    words = line.split()
                    meth = words[0]
                    for word in words:
                        try:
                            word = int(word)
                        except:
                            continue
                        # compare with certificat number
                        if cert_id == word:
                            # if has right
                            add_list_rights.append(meth)
                        if cert_id == -word:
                            del_list_rights.append(meth)

            results += add_list_rights
            results = uniq(results)

            for method in results:
                if method in del_list_rights:
                    results.remove(method)  

            if results == []:
                results.append("No Methods")

        return results

    def uncompatible(self):
        return _('You cannot change the certificate permissions')

class VariableClCertGroups(Variable):
    """
    Certificate Groups
    """
    type = "choice-list"
#    opt = ["--cert-group"]
#    metavalue = "perm[,perm2[..]]"

    def init(self):
        self.help = _("Certificate groups")
        self.label = _("Certificate groups")

    def choice(self):
        group_rights = self.Get('cl_core_group_rights_path')

        t = open(group_rights, 'r').read()
        result = []
        for line in t.splitlines():
            words = line.split()
            if words and len(words):
                if not words[0].startswith('#'):
                    result.append(words[0])
        if not 'all' in result:
            result.append('all')
        return result

    def get(self):
        cert_file = self.Get('cl_cert_crt_path')
        if OpenSSL is None:
            return []

        try:
            cert = open(cert_file, 'r').read()
            certobj = OpenSSL.crypto.load_certificate \
                                           (OpenSSL.SSL.FILETYPE_PEM, cert)
            com = certobj.get_extension(certobj.get_extension_count()-1). \
                                        get_data()
            groups = com.split(':')[1]
            groups_list = groups.split(',')
            return groups_list
        except (OpenSSL.crypto.Error,IOError) as e:
            return []

    def uncompatible(self):
        return _('You cannot change the certificate permissions')

class VariableClCertCrtPath(Variable):
    """
    Путь до сертификата (при указании иденификатора сертификата)
    """
    def get(self):
        return pathJoin(self.Get('cl_core_client_certs_path'),
                        "%s.crt"%self.Get('cl_cert_id'))
