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

# Copyright 2012-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 os, datetime, threading
import random, pickle
from cert_cmd import find_cert_id

# session management
class CoreWsdl():
    # delete client session from file (close session)
    def del_sid_from_file(self, sid):
        try:
            # temp file
            SID_FILE = self.sids_file
            SID_FILE_T = SID_FILE + 'temp'

            fd = open(SID_FILE, 'r')
            ft = open(SID_FILE_T, 'w')
            while 1:
                try:
                    # read all on one record
                    list_sid = pickle.load(fd)
                except:
                    break
                # Leave all but removed
                if sid != list_sid[0]:
                    pickle.dump(list_sid, ft)
            fd.close()
            ft.close()

            # copy all from temp file
            ft = open(SID_FILE_T, 'rb')
            fd = open(SID_FILE, 'wb')
            ft.seek(0)
            fd.write(ft.read())
            ft.close()
            fd.close()
            # delete temp file
            os.unlink(SID_FILE_T)
            return ['0']
        except:
            return ['1']

    # find session id in file
    def find_sid_in_file(self, sid):
        SID_FILE = self.sids_file
        # create, if file not exists
        if not os.path.exists(SID_FILE):
            temp = open(SID_FILE, 'w')
            temp.close()
        fd = open(SID_FILE, 'r')
        while 1:
            try:
                # read all on one record
                list_sid = pickle.load(fd)
            except:
                break
            # if session id found
            if sid == list_sid[0]:
                fd.close()
                return 1
        fd.close()
        return 0

    # add session id in file
    def add_sid_in_file(self, sid, cert_id, lang):
        # list Format (session number, cert number, time start session)
        list_sid = [sid, cert_id, datetime.datetime.now()]
        # session's file
        if not os.path.exists(self.sids):
            os.system('mkdir %s' %self.sids)
        SIDS_DIR = self.sids
        sid_file = SIDS_DIR+"/%d.sid" %sid

        # create session's file
        fp = open(sid_file, 'w')
        sid_list = [sid, 0, 0, lang]
        pickle.dump(sid_list,fp)  
        fp.close()

        # add session in list sessions
        fd = open(self.sids_file, 'a')
        pickle.dump(list_sid,fd)
        fd.close()
        return 0

    def set_sid_lang(self, sid, lang):
        SIDS_DIR = self.sids
        sid_file = os.path.join(SIDS_DIR, "%d.sid" %sid)
        if not os.path.isfile(sid_file):
            fp = open(sid_file, 'w')
            fp.close()
        fd = open(sid_file, 'r')
        try:
            list_sid = pickle.load(fd)
        except EOFError:
            list_sid = [sid, 0, 0, lang]
        fd.close()

        fp = open(sid_file, 'w')
        list_sid[3] = lang
        pickle.dump(list_sid,fp)
        fp.close()

    # issue number of new session (and registered its)
    def sid_cmp (self, sid, cert_id, lang):
        if sid < 0 or sid > self.max_sid: 
            sid = 0
        session = 1
        flag = 1
        # if session is new
        if sid == 0:
#        if True:
            while flag == 1:
                # generation number
                new_sid = random.randint(1, self.max_sid)
                # Check there is already the number
                flag = self.find_sid_in_file(sid)
            # add session id
            self.add_sid_in_file(new_sid, cert_id, lang)
            sid = new_sid

        # if session is old
        else:
            # find number in file registered
            # if not registered
            if not self.find_sid_in_file(sid):
                # add session id in file
                self.add_sid_in_file(sid, cert_id, lang)
            else:
                self.set_sid_lang(sid, lang)
                # set - old session
                session = 0

        # session id and flad (new or old) session
        result = []
        result.append(sid)
        result.append(session)
        return result

    def serv_init_session(self, sid, lang):
        DAY_CERT = 600
        curThread = threading.currentThread()
        certificate = curThread.client_cert
        results = []
        if certificate == None:
            return ([-3], [0])

        checked_id = find_cert_id(certificate, self.data_path, self.certbase)
        try:
            if int(checked_id) < 1:
                return ([-4], [0])
        except:
            return ([-4], [0])
#        client_cert_file = self.data_path + '/client_certs/' + str(checked_id)
        results = []
        cert_id = checked_id
        with open(self.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 len(words) > 3:
                    if words[0] == checked_id:
                        results.append(checked_id)
                        date = datetime.datetime.strptime \
                               (words[2]+' '+words[3], '%Y-%m-%d %H:%M:%S.%f')
                        d = datetime.datetime.now() - date
                        v = DAY_CERT - d.days  # How many days left certificate
                        if v < 0:
                            #Method deleted certificate
                            v = -2  # expiry date has passed
                        elif v > 60:  # For a long time, is not displayed to
                                      # the client
                            v = -1
                        results.append (v)
                        #return results
        if not results:
            return ([-4], [0])

        if sid < 0 or sid > self.max_sid:
            sid = 0
        session = 1
        flag = 1
        # if session is new
        if sid == 0:
            while flag == 1:
                # generation number
                new_sid = random.randint(1, self.max_sid)
                # Check there is already the number
                flag = self.find_sid_in_file(sid)
            # add session id
            self.add_sid_in_file(new_sid, cert_id, lang)
            sid = new_sid

        # if session is old
        else:
            # find number in file registered
            # if not registered
            if not self.find_sid_in_file(sid):
                # add session id in file
                self.add_sid_in_file(sid, cert_id, lang)
            else:
                self.set_sid_lang(sid, lang)
                # set - old session
                session = 0

        # session id and flad (new or old) session
        result = []
        result.append(sid)
        result.append(session)
        return (results, result)

    def serv_sid_info(self, sid):
        """ Get information about sid """
        cert_id = 0
        results = []
        SID_FILE = self.sids_file
        fd = open(SID_FILE, 'r')
        while 1:
            try:
                # read all on one record
                list_sid = pickle.load(fd)
            except:
                break
            # if sid found
            if sid == list_sid[0]:
                cert_id = list_sid[1]
        fd.close()

        # Get information about sid
        if cert_id == 0:
            return ["-1"]

        with open(self.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 words[0] == str(cert_id):
                    # certificate id
                    results.append(words[0])
                    # Date issue certificate
                    results.append(words[2]+' '+words[3])
                    # ip
                    results.append(words[4])
                    # mac
                    results.append(words[5])
                    # client type
                    results.append(words[6])
                    if not os.path.exists(self.sids):
                        os.makedirs(self.sids)
                    sid_path = self.sids + "/%d.sid"%sid
                    with open(sid_path) as fs:
                        # read info about session
                        sid_inf = pickle.load(fs)
                    # flag absence client
                    results.append(str(sid_inf[2]))

                    return results
        fd.close()
        return ["-2"]
