# vim: ts=4:sw=4:expandtab

# BleachBit
# Copyright (C) 2008-2017 Andrew Ziem
# https://www.bleachbit.org
#
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.


"""
Perform (or assist with) cleaning operations.
"""

from __future__ import absolute_import, print_function

from bleachbit import _, expanduser, expandvars
from bleachbit.FileUtilities import children_in_directory
from bleachbit.Options import options
from bleachbit import Command, FileUtilities, Memory, Special,GuiBasic

import glob
import logging
import os.path
import re
import sys
import warnings
import subprocess


if 'posix' == os.name:
    from bleachbit import Unix
elif 'nt' == os.name:
    from bleachbit import Windows

# Suppress GTK warning messages while running in CLI #34
warnings.simplefilter("ignore", Warning)

try:
    import gtk
    HAVE_GTK = True
except:
    HAVE_GTK = False

# a module-level variable for holding cleaners
backends = {}


class Cleaner:

    """Base class for a cleaner"""

    def __init__(self):
        self.actions = []
        self.id = None
        self.description = None
        self.name = None
        self.options = {}
        self.running = []
        self.warnings = {}

    def add_action(self, option_id, action):
        """Register 'action' (instance of class Action) to be executed
        for ''option_id'.  The actions must implement list_files and
        other_cleanup()"""
        self.actions += ((option_id, action), )

    def add_option(self, option_id, name, description):
        """Register option (such as 'cache')"""
        self.options[option_id] = (name, description)

    def add_running(self, detection_type, pathname):
        """Add a way to detect this program is currently running"""
        self.running += ((detection_type, pathname), )

    def auto_hide(self):
        """Return boolean whether it is OK to automatically hide this
        cleaner"""
        for (option_id, __name) in self.get_options():
            try:
                for cmd in self.get_commands(option_id):
                    for dummy in cmd.execute(False):
                        return False
                for ds in self.get_deep_scan(option_id):
                    if isinstance(ds, dict):
                        return False
            except Exception as e:
                logger = logging.getLogger(__name__)
                logger.exception('exception in auto_hide(), cleaner=%s, option=%s',
                                 self.name, option_id)
        return True

    def get_commands(self, option_id):
        """Get list of Command instances for option 'option_id'"""
        for action in self.actions:
            if option_id == action[0]:
                for cmd in action[1].get_commands():
                    yield cmd
        if option_id not in self.options:
            raise RuntimeError("Unknown option '%s'" % option_id)

    def get_deep_scan(self, option_id):
        """Get dictionary used to build a deep scan"""
        for action in self.actions:
            if option_id == action[0]:
                for ds in action[1].get_deep_scan():
                    yield ds
        if option_id not in self.options:
            raise RuntimeError("Unknown option '%s'" % option_id)

    def get_description(self):
        """Brief description of the cleaner"""
        return self.description

    def get_id(self):
        """Return the unique name of this cleaner"""
        return self.id

    def get_name(self):
        """Return the human name of this cleaner"""
        return self.name

    def get_option_descriptions(self):
        """Yield the names and descriptions of each option in a 2-tuple"""
        if self.options:
            for key in sorted(self.options.keys()):
                yield (self.options[key][0], self.options[key][1])

    def get_options(self):
        """Return user-configurable options in 2-tuple (id, name)"""
        if self.options:
            for key in sorted(self.options.keys()):
                yield (key, self.options[key][0])

    def get_warning(self, option_id):
        """Return a warning as string."""
        if option_id in self.warnings:
            return self.warnings[option_id]
        else:
            return None

    def is_running(self):
        """Return whether the program is currently running"""
        resp_cli=""
        logger = logging.getLogger(__name__)
        for running in self.running:
            test = running[0]
            pathname = running[1]
            if 'exe' == test and 'posix' == os.name:
                if Unix.is_running(pathname):
                    #print "debug: process '%s' is running" % pathname
                    logger.debug("Debug: process '%s' is running", pathname)
                    if options.get("close_run"):
                        if not subprocess.mswindows:
                            #print "debug: Closing process '%s'" % pathname
                            if "--preset" in sys.argv:
                                resp_cli = raw_input("Do you Want BleachBit to Close " + pathname + " y/n : ")
                            else:
                                resp = GuiBasic.message_dialog(None,"Do you Want BleachBit to Close " + pathname,gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO)
                            if gtk.RESPONSE_YES == resp or resp_cli.lower() == "y":
                            # user cancelled, so don't toggle option
                                logger.debug("Debug: Closing process '%s'",pathname)
                  
              subprocess.check_output(["killall", "-9", pathname])
                            if not Unix.is_running(pathname):
                                logger.debug("Debug: Closing process '%s' successful",pathname)
                                return False
                    return True
            elif 'exe' == test and 'nt' ==
 os.name:
                if Windows.is_process_running(pathname):
                    #print "debug: process '%s' is running" % pathname
                    logger.debug("Debug: process '%s' is running", pathname)
                    if options.get("close_run"):
                        if subprocess.mswindows:
                            #print "debug: Closing process '%s'" % pathname
                            if "--preset" in sys.argv:
                                resp_cli = raw_input("Do you Want BleachBit to Close " + pathname + " y/n : ")
                            else:
                                resp = GuiBasic.message_dialog(None,"Do you Want BleachBit to Close " + pathname,gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO)
                            if gtk.RESPONSE_YES == resp or resp_cli.lower() == "y":
                                logger.debug("debug: Closing process '%s'",pathname)
                                subprocess.check_output(["taskkill", "/IM", pathname])
                            if not Windows.is_process_running(pathname):
                                logger.debug("debug: Closing process '%s' successful",pathname)
                                return False
                    logger.debug("process '%s' is running", pathname)
                    return True
            elif 'exe' == test and 'nt' == os.name:
                if Windows.is_process_running(pathname):
                    logger.debug("process '%s' is running", pathname)
                    return True
            elif 'pathname' == test:
                expanded = expanduser(expandvars(pathname))
                for globbed in glob.iglob(expanded):
                    if os.path.exists(globbed):
