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

# Copyright 2010-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 sys
import os
import subprocess
from calculate.core.server.core_interfaces import MethodsInterface

from calculate.lib.utils.files import pathJoin, readFile
from calculate.lib.utils.common import getPagesInterval
from calculate.lib.cl_lang import getLazyLocalTranslate, setLocalTranslate

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

__ = getLazyLocalTranslate(_)


class Request(MethodsInterface):
    """
    Объект работы с запросами на создание сертификатов
    """

    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
