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

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

import sys, os
import subprocess

from calculate.lib.utils.files import pathJoin,readFile
from calculate.lib.utils.common import getPagesInterval
from calculate.lib.datavars import VariableError
from calculate.lib.cl_lang import getLazyLocalTranslate, setLocalTranslate
setLocalTranslate('cl_core3',sys.modules[__name__])

from calculate.core import datavars
import traceback

__ = getLazyLocalTranslate(_)

class Request:
    """
    Объект работы с запросами на создание сертификатов
    """
    def show_request_meth (self, page_count, page_offset):
        """
        Отобразить таблицу с текущими запросами
        """
        dv = self.clVars
        list_req_id = dv.Get('cl_list_req_id')
        try:
            list_req_id.sort(key=lambda x:int(x))
        except ValueError:
            list_req_id.sort()

        if not list_req_id:
            self.printSUCCESS(_('No requests'))


        head = ['Id',_('UserName'),'IP','MAC',_('Date'), _('Location'),
                _('Group')]
        body = []
        fields = ['cl_req_id','','','','','','']

        for req in list_req_id[page_offset:page_offset+page_count]:
            dv.Set('cl_req_id', req)
            mac = dv.Get('cl_req_mac')
            ip = dv.Get('cl_req_ip')
            date = dv.Get('cl_req_date')
            username = dv.Get('cl_req_user_name')
            location = dv.Get('cl_req_location')
            group = dv.Get('cl_req_group')
            if not group:
                group = _('Not signed')
            body.append([str(req),username,ip,mac,date,location,group])

        if body:
            self.printTable(_("List of requests"), head, body,
                         fields = fields, onClick = 'core_detail_request')
            num_page,count_page = getPagesInterval(
                                    page_count, page_offset,
                                    len(list_req_id))
            self.printSUCCESS(_('page %d from ')%num_page+str(count_page))
            return True

    def confirm_request_meth(self, client_certs,cert_path,
                             cl_req_csr_path,
                             cl_req_crt_path,cl_req_group):
        """
        Подтвердить запрос на сертификат и создать его
        """
        server_cert = cert_path + '/root.crt'
        server_key = cert_path + '/root.key'

        if not os.path.exists(cl_req_csr_path):
            self.printERROR (_("Signature request %s not found") %
                cl_req_csr_path)
            return False

        if os.path.exists(cl_req_crt_path):
            self.printWARNING (_("Certificate %s has been signed") %
                cl_req_crt_path)
            return False

        group = "group:%s" %cl_req_group
        config = pathJoin(client_certs,'ssl-client.cfg')
        if os.path.exists(config):
            os.unlink(config)

        cfg_text = ("[ ssl_client ]\n"
            "basicConstraints = CA:FALSE\n"
            "nsCertType = client\n"
            "keyUsage = digitalSignature, keyEncipherment\n"
            "extendedKeyUsage = clientAuth\n"
            "nsComment = %s") %group
        fc = open(config, 'w')
        fc.write(cfg_text)
        fc.close()

        cmd = ("openssl x509 -req -days 11000 -CA %s -CAkey %s "
                    "-CAcreateserial "
                    "-extfile %s -extensions ssl_client -in %s -out %s") \
                    %(server_cert, server_key, config, 
                     cl_req_csr_path, cl_req_crt_path)
        PIPE = subprocess.PIPE
        p = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE,
        stderr=subprocess.STDOUT, close_fds=True)
        p.wait()
        return True

    def del_request_meth(self, certbase, request, cert, id_del_req):

        # chect exists request and certificate files 
        if not os.path.exists(request) and not os.path.exists(cert):
            self.printERROR (_('Request or certificate with ID = %s not '
                                                    'found!')%id_del_req)
            return False

        if not os.path.exists(request):
            self.printERROR (_("Request %s not found!") %request)

        if os.path.exists(cert):
            self.printWARNING (_("Request signed"))

        certbase_temp = certbase + '_temp'
        # create temp file
        ft = open(certbase_temp, 'w')
        with open(certbase) as fd:
            t = fd.read()
            # See each line
            for line in t.splitlines():
                # and each word in line
                words = line.split()
                    # if in line present certificate id
                if not words[0] == id_del_req:
                    ft.write(line + '\n')
        ft.close()
        fd.close()

        with open(certbase,'w') as f:
            f.write(readFile(certbase_temp))
        os.unlink(certbase + '_temp')
        if os.path.exists(request):
            os.unlink (request)
            self.printSUCCESS (_("Signature request deleted"))
        if os.path.exists(cert):
            os.unlink (cert)
            self.printSUCCESS (_("Certificate deleted"))
        return True
