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

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

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

from calculate.lib.cl_lang import setLocalTranslate
from calculate.lib.utils.files import readLinesFile, pathJoin, readFile

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


class VariableClListReqId(Variable):
    def get(self):
        data_path = self.Get('cl_core_data')
        result = []
        cert_dir = data_path + '/client_certs/'
        for filename in glob.glob(cert_dir + "*"):
            if filename.endswith('.csr'):
                temp = filename.split('.')[0].split('/')
                id = temp[len(temp) - 1]
                result.append(id)
        return result


class VariableClReqId(Variable):
    """
    Certificate Identification
    """
    type = "choice"
    opt = ["-r"]
    metavalue = "REQ_ID"
    untrusted = True

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

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

    def check(self, req_id):
        if not req_id:
            raise VariableError(_("The request ID is a required parameter"))
        try:
            int(req_id)
        except (ValueError, TypeError):
            raise VariableError(_("The request ID must be int"))

    def raiseNothingValue(self):
        raise VariableError(_("Not found any requests"))

    def get(self):
        # if not self.choice():
        #    self.raiseNothingValue()
        return ""


class VariableClPageLimit(Variable):
    """
    Ограничение ????
    """
    type = "int"
    opt = ["--page-limit"]
    metavalue = "PAGE_LIMIT"
    element = 'input'

    def init(self):
        self.help = _("set the page limit value")
        self.label = _("Page limit")

    def check(self, limit):
        try:
            int(limit)
        except ValueError:
            raise VariableError(_("The limit number must be int"))


class VariableClPageCount(Variable):
    """
    Количество записей на страницу
    """
    type = "int"
    opt = ["--page-count"]
    metavalue = "PAGE_COUNT"
    element = 'input'

    def init(self):
        self.help = _("set the page count value")
        self.label = _("Page count")

    def get(self):
        return self.Get('cl_page_max')

    def set(self, value):
        if not value or int(value) <= 0:
            value = self.Get('cl_page_max')
        return value


class VariableClPageOffset(Variable):
    """
    Смещение по записям относительно начала
    """
    type = "int"
    opt = ["--page-offset"]
    metavalue = "PAGE_OFFSET"
    element = 'input'
    value = "0"

    def init(self):
        self.help = _("set the page offset value")
        self.label = _("Page offset")

    def set(self, value):
        try:
            max_id = int(self.Get('cl_page_max'))
            value = int(value)
            if value < 0:
                value = max_id + value
            return str(max(0, min(int(value), max_id - 1)))
        except ValueError:
            return str(0)


class VariableClPageMax(ReadonlyVariable):
    """
    Максимальное количество записей
    """
    type = "int"

    def get(self):
        return "0"


class VariableClReqBaseData(Variable):
    """
    """

    def get(self):
        req_id = self.Get('cl_req_id')
        certbase = self.Get('cl_core_database')

        for line in readLinesFile(certbase):
            data = line.strip().split()
            if len(data) < 6:
                continue
            data += [""] * (8-len(data))
            if data[0] == str(req_id):
                return data
        return [''] * 8


class VariableClReqData(Variable):
    """
    Данные о запросах
    """

    def get(self):
        try:
            import OpenSSL

            req_file = self.Get('cl_req_csr_path')
            if os.path.exists(req_file):
                fp = open(req_file, 'r')
                request = fp.read()
                fp.close()
                reqobj = OpenSSL.crypto.load_certificate_request(
                    OpenSSL.SSL.FILETYPE_PEM, request)
                subject = reqobj.get_subject().get_components()
                return subject
        except ImportError:
            OpenSSL = None
        return [['', '']] * 6


class VariableClReqIp(ReadonlyVariable):
    """
    Ip Request
    """

    def init(self):
        self.help = _("request IP address")
        self.label = _("Request IP address")

    def uncompatible(self):
        return 'Ip adress'

    def get(self):
        return self.Get('cl_req_base_data')[4]


class VariableClReqMac(ReadonlyVariable):
    """
    Mac Adress Request
    """

    def init(self):
        self.help = _("request MAC adress")
        self.label = _("Request MAC address")

    def uncompatible(self):
        return 'Mac adress'

    def get(self):
        return self.Get('cl_req_base_data')[5]


class VariableClReqDate(ReadonlyVariable):
    """
    Date send Request
    """

    def init(self):
        self.help = _("request date")
        self.label = _("Request date")

    def uncompatible(self):
        return 'Request Date'

    def get(self):
        words = self.Get('cl_req_base_data')
        if words:
            return '%s %s' % (words[2], words[3])
        else:
            return ""


class VariableClReqUserName(ReadonlyVariable):
    """
    UserName Owner Request
    """

    def init(self):
        self.help = _("request owner username")
        self.label = _("Request owner username")

    def uncompatible(self):
        return 'User name request owner'

    def get(self):
        subject = self.Get('cl_req_data')
        for item in subject:
            if item[0] == 'OU':
                return item[1]
        return ''


class VariableClReqLocation(ReadonlyVariable):
    """
    Location Owner Request
    """

    def init(self):
        self.help = _("request location")
        self.label = _("Request location")

    def uncompatible(self):
        return 'Location'

    def get(self):
        subject = self.Get('cl_req_data')
        for item in subject:
            if item[0] == 'L':
                return item[1]
        return ''


class VariableClReqGroup(Variable):
    """
    Certificate Group
    """
    type = "choice"
    opt = ["-g"]
    metavalue = "REQ_GROUP"
    untrusted = True

    def init(self):
        self.help = _("set the certificate group")
        self.label = _("Certificate group")

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

        t = readFile(group_rights)
        result = []
        for line in t.splitlines():
            words = line.split()

            if not words[0].startswith('#'):
                result.append(words[0])
        if 'all' not in result:
            result.append('all')
        return result

    def get(self):
        try:
            import OpenSSL

            try:
                cert_file = self.Get('cl_req_crt_path')
                fp = open(cert_file, 'r')
                cert = fp.read()
                fp.close()
                certobj = OpenSSL.crypto.load_certificate(
                    OpenSSL.SSL.FILETYPE_PEM, cert)
                com = certobj.get_extension(
                    certobj.get_extension_count() - 1).get_data()
                return com.split(':')[1]
            except OpenSSL.crypto.Error:
                return ""
        except (IOError, ImportError):
            return ""

    def check(self, group):
        if not group:
            raise VariableError(_("Group permissions is a required parameter"))
        group_rights = self.Get('cl_core_group_rights_path')

        if group == 'all':
            return
        t = readFile(group_rights)
        for line in t.splitlines():
            words = line.split()
            if words[0].startswith('#'):
                continue
            if group == words[0]:
                return
        raise VariableError(_("Group %s does not exist") % group)


class VariableClReqCrtPath(ReadonlyVariable):
    """
    Путь до сертификата при использовании запроса на сертификат
    """

    def get(self):
        return pathJoin(self.Get('cl_core_client_certs_path'),
                        '%s.crt' % self.Get('cl_req_id'))


class VariableClReqCsrPath(ReadonlyVariable):
    """
    Путь до запроса
    """

    def get(self):
        return pathJoin(self.Get('cl_core_client_certs_path'),
                        '%s.csr' % self.Get('cl_req_id'))
