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

# Copyright 2012-2015 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
import time
from os import path
import pickle
from threading import Lock
from calculate.core.server.core_interfaces import CoreServiceInterface
from calculate.lib.utils.tools import ignore


class CoreWsdl(CoreServiceInterface):
    sid_pid_locker = Lock()

    def del_sid_pid(self, sid):
        # delete conformity pid and sid of sid_pid file
        if not os.path.exists(self.sids_pids):
            temp = open(self.sids_pids, 'w')
            temp.close()
        sid_pid_t = self.sids_pids + '_temp'

        with self.sid_pid_locker:
            fd = open(self.sids_pids, 'r')
            ft = open(sid_pid_t, 'w')
            while 1:
                try:
                    # read out on 1 record
                    list_sid = pickle.load(fd)
                except (IOError, KeyError, EOFError):
                    break
                if sid != list_sid[0]:
                    pickle.dump(list_sid, ft)
                else:
                    # end process pid = list_sid[1]
                    self.serv_pid_kill(list_sid[1], sid)
                    # delete this of process file
                    while self.glob_process_dict[list_sid[1]]['status'] == 1:
                        time.sleep(0.1)
                    self.del_pid(list_sid[1])
                    # delete process file
                    rm_fn = path.join(self.pids, "%d.pid" % list_sid[1])
                    if path.exists(rm_fn):
                        with ignore(OSError):
                            os.unlink(rm_fn)
            fd.close()
            ft.close()

            ft = open(sid_pid_t, 'rb')
            fd = open(self.sids_pids, 'wb')
            ft.seek(0)
            fd.write(ft.read())
            ft.close()
            fd.close()

            # delete sid file
            sid_file = os.path.join(self.sids, "%d.sid" % sid)
            if os.path.exists(sid_file):
                os.unlink(sid_file)
            os.unlink(sid_pid_t)
        return 0

    def del_pid_from_sid_pid(self, pid):
        # delete conformity pid and sid of sid_pid file
        if not os.path.exists(self.sids_pids):
            temp = open(self.sids_pids, 'w')
            temp.close()
        sid_pid_t = self.sids_pids + '_temp'

        with self.sid_pid_locker:
            fd = open(self.sids_pids, 'r')
            ft = open(sid_pid_t, 'w')
            while 1:
                try:
                    # read out on 1 record
                    list_sid = pickle.load(fd)
                except (KeyError, EOFError, IOError):
                    break
                if pid != list_sid[1]:
                    pickle.dump(list_sid, ft)
            fd.close()
            ft.close()

            ft = open(sid_pid_t, 'rb')
            fd = open(self.sids_pids, 'wb')
            ft.seek(0)
            fd.write(ft.read())
            ft.close()
            fd.close()

            # delete temp file
            os.unlink(sid_pid_t)
        return 0

    def find_sid_pid_file(self, sid):
        results = []
        with self.sid_pid_locker:
            if not os.path.exists(self.sids_pids):
                temp = open(self.sids_pids, 'w')
                temp.close()
            fd = open(self.sids_pids, 'r')
            while 1:
                try:
                    # read out on 1 record
                    list_sid = pickle.load(fd)
                except (IOError, KeyError, EOFError):
                    break
                if sid == list_sid[0]:
                    results.append(list_sid[1])
            if not results:
                results.append(0)
            fd.close()
        return results

    def serv_pid_info(self, sid, pid):
        f = 0
        results = []
        # Check pid presence and conformity sid

        with self.sid_pid_locker:
            fd = open(self.sids_pids, 'r')
            while 1:
                try:
                    # read out on 1 record
                    list_sid = pickle.load(fd)
                except (IOError, KeyError, EOFError):
                    break
                if sid == list_sid[0]:
                    if pid == list_sid[1]:
                        f = 1
            fd.close()

            # Get information about pid
            if f == 1:
                _t = self.glob_process_dict[pid]
                # process id
                results.append(str(pid))
                # current state
                results.append(str(self.glob_process_dict[pid]['status']))
                # start time
                results.append(str(self.glob_process_dict[pid]['time']))
                # process (function) name
                results.append(str(self.glob_process_dict[pid]['name']))
                # process soap method name
                results.append(str(self.glob_process_dict[pid]['method_name']))
        return results

    def add_sid_pid(self, sid, pid):
        """
        add conformity pid and sin in sid_pid file
        """
        with self.sid_pid_locker:
            if not os.path.exists(self.sids_pids):
                with open(self.sids_pids, 'w'):
                    pass
            try:
                with open(self.sids_pids, 'a') as fd:
                    pickle.dump([sid, pid], fd)
                return 0
            except (OSError, IOError, KeyError, EOFError):
                return 1
