# -*- coding: utf-8 -*-
#
# plugins/ProcessWatcher/__init__.py
#
# This file is a plugin for EventGhost.
# Copyright © 2005-2016 EventGhost Project <http://www.eventghost.org/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.

import eg

eg.RegisterPlugin(
    name = "Process WatcherMod",
    author = (
        "Bitmonster",
        "DranDane",
        "Sem;colon",
    ),
    version = "1.1.0",
    guid = "{82BADF9F-D809-4EBC-A540-CCBF7563F8D0}",
    description = (
        "Generates events if a process is created or destoyed"
    ),
    url = "http://www.eventghost.org/forum/viewtopic.php?f=10&t=1207",
    icon = (
        "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABuklEQVR42o1Sv0tCYRQ9"
        "L1FccpCEB73wVy1NjTrUPxD1lgZp0dWKaAhXxWhoyWgoIUjHBEH65RSE0CAUgWIPLAqR"
        "gkAQIQXR8nW/Z0ai6btweJfDd847934fhz8VCARkqCjTmBGra+sc67kOGQqFZIfDMVCo"
        "1WphMpng9/vxkMvi9u6e4zp/ZmStVkOpVOor1mg00Ol0CIfDKBQK/Q1isRhcLhedJpIn"
        "vHXkI+D5SUSj+0in0wMM4mSw6WqL9whLhHeCYAA/tobo9twQgxsyEMjglUj6IE7YIJxQ"
        "gk9K8DwsgTLCMjGGdvJxJibMUgJ+hUaYGWyQSCQQDO7+ZO8uo1EHn8/2v4Hb7UYmkxl4"
        "jY1GA9lsFrlcDl+fDZxfJNsGHo9H1QNiVa/XlQSiuIAp2wS466ukHNjaUauHXq+H0+n8"
        "HYPrzF+pVHriSpLUxbGHJAgCIpFIr0EqlYI0KmH6Y1o5XC6XaaFBpW+1WqhWq7BYLLRI"
        "X9ciFQNRFJHP53FoO4T3xdsTu9lsolgswm63Kz1b9tPTI6xmAVzk+Eg+PbtUvQNWstxS"
        "xHv7B+1bEBfnVd8CK6vFrIhZ/w1wBAQrC42uqQAAAABJRU5ErkJggg=="
    ),
)

from eg.cFunctions import GetProcessDict
from threading import Thread, Event
from time import sleep
from os.path import splitext
from fnmatch import fnmatch

import pythoncom
from win32com.client import Moniker


class Process(eg.PluginClass):

    def __init__(self):
        self.AddAction(GetProcessByPid)
        self.AddAction(GetProcessesByName)

    def __start__(self):
        self.stopEvent = Event()
        self.thread1 = Thread(
            target=self.ThreadLoop,
            name="ProcessWatcherCreationThread",
            args=(self.stopEvent, "Start")
        )
        self.thread2 = Thread(
            target=self.ThreadLoop,
            name="ProcessWatcherDeletionThread",
            args=(self.stopEvent, "Stop")
        )
        self.thread1.start()
        self.thread2.start()

    def __stop__(self):
        if (self.thread1 or self.thread2 or self.threadTest) is not None:
            self.stopEvent.set()

    def ThreadLoop(self, stopThreadEvent, EventType):
        timeout = 100
        pythoncom.CoInitialize()

        wmi = Moniker('winmgmts:')
        events = wmi.ExecNotificationQuery("Select * From WIN32_Process{0}Trace".format(EventType))

        while not stopThreadEvent.isSet():
            try:
                event = events.NextEvent(timeout)
            except:
                pass
            else:
                eg.TriggerEvent({"Start": "Created.", "Stop": "Destroyed."}[EventType] + event.ProcessName, prefix="Process", payload={"pid": event.ProcessID})

class GetProcessByPid(eg.ActionBase):
    name  = "Get process by PID"
    description  =  """Returns True if the PID exists and False if not."""

    class text:
        pid = "PID:"

    def __call__(self, pid):
        processes = GetProcessDict()
        return pid in processes

    def Configure(self, pid=0):
        panel = eg.ConfigPanel()
        text = self.text
        wx_pid = panel.SpinIntCtrl(pid, min=0)
        st_pid = panel.StaticText(text.pid)

        panel.AddLine(st_pid,wx_pid)

        while panel.Affirmed():
            panel.SetResult(wx_pid.GetValue(),)


class GetProcessesByName(eg.ActionBase):
    name  = "Get processes by name"
    description  =  """Returns an array of dicts with processes (pid and name) that match a process name."""

    class text:
        processName = "Process name:"

    def __call__(self, processName):
        processes = GetProcessDict()
        pids = set(processes.iterkeys())
        result=[]
        for pid in pids:
            name = splitext(processes[pid])[0]
            if fnmatch(name,processName):
                result.append({"pid":pid,"name":name})
        return result

    def Configure(self, processName=""):
        panel = eg.ConfigPanel()
        text = self.text
        wx_processName = panel.TextCtrl(processName)
        st_processName = panel.StaticText(text.processName)

        panel.AddLine(st_processName,wx_processName)

        while panel.Affirmed():
            panel.SetResult(wx_processName.GetValue(),)