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

# Copyright 2012-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 threading
import os
import hashlib
import datetime
from calculate.lib.utils.files import readFile

MAX = 10000

# Sign client certificate
def serv_post_client_request(request, data_path,
                             ip, mac, client_type, client_certbase, cert_path):
    if not os.path.exists(cert_path + '/root.crt') or \
            not os.path.exists(cert_path + '/root.key'):
        return '-1'

    if not os.path.exists(client_certbase):
        if not os.path.exists(data_path + '/client_certs/'):
            os.makedirs(data_path + '/client_certs/')
        fp = open(client_certbase, 'w')
        fp.close()

    # get ip
    cur_thread = threading.currentThread()
    try:
        ip = cur_thread.REMOTE_ADDR
    except AttributeError:
        ip = 'localhost'

    # Finding Id for the current certificate
    id_file = data_path + '/client_certs/id.int'

    if os.path.exists(id_file):
        i = int(readFile(id_file))
    else:
        with open(client_certbase) as fd:
            t = fd.read()
        count = len(t.splitlines()) + 1
        with open(id_file, 'w') as fi:
            fi.write(str(count))
        i = count

    req_file = data_path + '/client_certs/' + str(i) + '.csr'

    # Record of request of the client in file req_file
    with open(req_file, 'w') as f:
        f.write(request)

    md5 = hashlib.md5()
    md5.update(request)
    md5sum = md5.hexdigest()
    date = datetime.datetime.now()

    # record
    with open(client_certbase, "a") as fc:
        fc.write("%d %s %s %s %s %s\n" %
            (i, md5sum, date, ip, mac, client_type))

    # record next Id in id.int file
    i += 1
    with open(id_file, 'w') as fi:
        temp = str(i)
        fi.write(temp)
    return str(i - 1)


def serv_get_client_cert(req_id, request, data_path, client_certbase,
                         cert_path, localuser=None):
    req_file = data_path + '/client_certs/' + req_id + '.csr'
    if not os.path.exists(req_file):
        return '1'

    cert_file = data_path + '/client_certs/' + req_id + '.crt'
    if not os.path.exists(cert_file):
        return '2'

    # read client certificate in buffer
    fp = open(cert_file, 'r')
    cert = fp.read()
    fp.close()

    md5 = hashlib.md5()
    md5.update(cert)
    md5sum = md5.hexdigest()
    date = datetime.datetime.now()

    ft = open(client_certbase + '_temp', 'w')
    # open file with server certificate certbase
    with open(client_certbase) as fd:
        t = fd.read()
        # See each line
        for line in t.splitlines():
            # and each word in line
            words = line.split(' ')
            if not words:
                continue
            if words[0] == req_id:
                try:
                    cur_thread = threading.currentThread()
                    ip = cur_thread.REMOTE_ADDR
                except AttributeError:
                    ip = 'localhost'
                if not request == words[1]:
                    fd.close()
                    ft.close()
                    os.unlink(client_certbase + '_temp')
                    return '3'
                mac = words[5]
                client_type = words[6]
                if localuser:
                    line = ("%s %s %s %s %s %s %s" % (req_id, md5sum, date, ip, mac,
                                                   client_type, localuser))
                else:
                    line = ("%s %s %s %s %s %s" % (req_id, md5sum, date, ip, mac,
                                                   client_type))
            ft.write(line + '\n')

    # copy all from temp file
    ft = open(client_certbase + '_temp', 'rb')
    fd = open(client_certbase, 'wb')
    ft.seek(0)
    fd.write(ft.read())
    ft.close()
    fd.close()
    # delete temp file
    os.unlink(client_certbase + '_temp')
    os.unlink(req_file)

    cert_file_path = os.path.join(cert_path, 'root.crt')
    if not os.path.exists(cert_file_path):
        open(cert_file_path, 'w').close()
    ca_root = readFile(cert_file_path)
    return [cert, ca_root]


# sign server certificate
def serv_post_server_request(request, data_path,
                             ip, mac, serv_certbase, cert_path):
    if (not os.path.exists(cert_path + '/root.crt') or
            not os.path.exists(cert_path + '/root.key')):
        return '-1'

    if not os.path.exists(serv_certbase):
        if not os.path.exists(data_path + '/server_certs/'):
            os.makedirs(data_path + '/server_certs/')
        fp = open(serv_certbase, 'w')
        fp.close()

    # get ip
    cur_thread = threading.currentThread()
    try:
        ip = cur_thread.REMOTE_ADDR
    except AttributeError:
        # print "EXCEPT ip = curThread.REMOTE_ADDR!!!!!!"
        ip = 'not_defined'

    # Finding Id for the current certificate
    id_file = data_path + '/server_certs/id.int'

    if os.path.exists(id_file):
        with open(id_file, 'r') as fi:
            temp = fi.read()
            i = int(temp)
    else:
        with open(serv_certbase) as fd:
            t = fd.read()
            count = len(t.splitlines())

        count += 1
        with open(id_file, 'w') as fi:
            fi.write(str(count))
        i = count

    req_file = data_path + '/server_certs/' + str(i) + '.csr'

    # Record of request of the client in file REQ_FILE
    with open(req_file, 'w') as f:
        f.write(request)

    md5 = hashlib.md5()
    md5.update(request)
    md5sum = md5.hexdigest()
    date = datetime.datetime.now()

    # record
    with open(serv_certbase, "a") as fc:
        fc.write("%d %s %s %s %s\n" % (i, md5sum, date, ip, mac))

    # record next Id in id.int file
    with open(id_file, 'w') as fi:
        fi.write(str(i + 1))
    return str(i)


def serv_get_server_request(req_id, request, data_path, serv_certbase,
                            cert_path):
    req_file = data_path + '/server_certs/' + req_id + '.csr'
    if not os.path.exists(req_file):
        return '1'

    cert_file = data_path + '/server_certs/' + req_id + '.crt'
    if not os.path.exists(cert_file):
        return '2'

    # fp = open(REQ_FILE, 'r')
    #    req = fp.read()
    #    fp.close()

    # read client certificate in buffer
    fp = open(cert_file, 'r')
    cert = fp.read()
    fp.close()

    md5 = hashlib.md5()
    md5.update(cert)
    md5sum = md5.hexdigest()
    date = datetime.datetime.now()

    ft = open(serv_certbase + '_temp', 'w')
    # open file with server certificate certbase
    with open(serv_certbase) as fd:
        t = fd.read()
        # See each line
        for line in t.splitlines():
            # and each word in line
            words = line.split(' ')
            if words[0] == req_id:
                cur_thread = threading.currentThread()
                try:
                    ip = cur_thread.REMOTE_ADDR
                except AttributeError:
                    return '3'
                if not request == words[1]:
                    fd.close()
                    ft.close()
                    os.unlink(serv_certbase + '_temp')
                    return '3'
                mac = words[5]
                line = ("%s %s %s %s %s" % (req_id, md5sum, date, ip, mac))
            ft.write(line + '\n')

    # copy all from temp file
    ft = open(serv_certbase + '_temp', 'rb')
    fd = open(serv_certbase, 'wb')
    ft.seek(0)
    fd.write(ft.read())
    ft.close()
    fd.close()
    # delete temp file
    os.unlink(serv_certbase + '_temp')
    os.unlink(req_file)

    if not os.path.exists(cert_path + '/ca_root.crt'):
        open(cert_path + '/ca_root.crt', 'w').close()
    ca_root = readFile(cert_path + '/ca_root.crt')
    return [cert, ca_root]
