# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.


__maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>'

from elisa.base_components.action import Action

from twisted.internet import defer, protocol, reactor

import os

class ProcessObserver(protocol.ProcessProtocol):

    def __init__(self):
        self.reset()

    def reset(self):
        self.deferred = defer.Deferred()

    def processEnded(self, status):
        self.deferred.callback(status)


class SpawnProcessAction(Action):
    """
    This Action starts and spawns a process
    
    @ivar executable:   the executable
    @type executable:   unicode
    @ivar running:      is the program running?
    @type running:      bool
    @ivar args:         the arguments to start the process with
    @type args:         tuple          
    @ivar deferred:     the deferred that will be called after the process
                        endet 
    """

    def __init__(self):
        self._running = False
        self._exec = None
        self._args = None
        self._path = None
        self._protocol = ProcessObserver()
        self._protocol.deferred.addCallback(self._protocol_callback)

    def running__get(self):
        return self._runnig

    def executable__set(self, exec_string):
        if not self._running:
            self._exec = exec_string
        # raise Exception here

    def executable__get(self):
        return self._exec

    def path__set(self, path):
        if not self._running:
            self._path = path
        # raise Exception?

    def path__get(self):
        return self._path

    def args__get(self, args):
        if not self._running:
            self._args = args
        # raise Exception here

    def deferred__get(self):
        return self._protocol.deferred

    def _protocol_callback(self):
        self._running = False

    def __call__(self, sth):

        exc = self._exec

        args = []

        if ' ' in exc:
            args = exc.split(' ')
            exc = args[0]
        else:
            args.append(exc)

        if exc[0] != '/':
            pathes = os.environ.get('PATH')
            for path in pathes.split(':'):
                test_path = "%s/%s" % (path, exc)
                if os.path.exists(test_path):
                    exc = test_path
                    break

        path = self._path

        self._protocol.reset()
        process = reactor.spawnProcess(self._protocol,
                                        exc,
                                        path=path,
                                        args=args,
                                        env=None)
        self._pid = process.pid
        self.debug('called %s. Pid:%s'  % (exc, self._pid))
