#!/usr/bin/python
# -*- coding: utf-8 -*-
# utils.py
#  
#  Author: Laudeci Oliveira <laudeci@gmail.com>
#          Rafael Proença   <cypherbios@ubuntu.com>
# 
#  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 2 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, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#  USA

import apt_inst
import apt_pkg
import gtk
import math
import fnmatch
import os
import pygtk
import shutil
import urllib
import gnomevfs
import re
import tarfile
import bz2

import config

def isValidFileName(filename):
    try:
        p=re.compile('[^0-9A-Za-z_\+\.,-]+')
        if p.search(filename):
            return False
        else:
            return True
    except:
        return False
    
def updateUI():
    while gtk.events_pending(): gtk.main_iteration() 

#  Do case insensitive wildcard search on column 1.
def TreeViewSearch( model, column, key, it, data):
    key, title = key.lower(), model.get_value(it, column).lower()
    return title.find(key) == -1
        
def getCDROM():
    vol_monitor =  gnomevfs.VolumeMonitor()
    volume = gnomevfs.Volume()
    drives = []
    for volume in vol_monitor.get_mounted_volumes():
        if volume.get_hal_udi() != None:
            vol_type = volume.get_device_type()
            if vol_type == gnomevfs.DEVICE_TYPE_CDROM or vol_type == gnomevfs.DEVICE_TYPE_VIDEO_DVD:
                drives.append(volume.get_drive())
    
    return drives
            
def packageTooltip(widget, e, tooltips, cell, emptyText="no information"):
     """ If emptyText is None, the cursor has to enter widget from a side that contains an item, otherwise no tooltip will be displayed. """
     try:
         (path, col, x, y) = widget.get_path_at_pos(int(e.x), int(e.y))
         it = widget.get_model().get_iter(path)
         value = widget.get_model().get_value(it, config.C_PKG)
         tooltips.set_tip(widget, value.get_pkg_ShortDescription())
         tooltips.enable()
     except:
         tooltips.set_tip(widget, emptyText)
            
def checkAccess(path):
    """Checks file/folder permissions and returns True if the file/folder could be accessed"""
    mRet = False
    if pathExists(path):
        if os.access(path, os.R_OK | os.W_OK | os.X_OK):
            mRet = True
        return mRet

def copyFile(source , destination):
    try:
        dest = os.path.dirname(destination)
        if not pathExists(dest):
            mkdir(dest)
        
        shutil.copyfile(source , destination)
    except Exception , e :
        print str(e)

def delFile( path):
    """ Deletes a file if it exists"""
    if fileExist(path):
        os.remove(path)
    
def removePath( path):
    """ Removes a directory path """
    try:
        shutil.rmtree(path, ignore_errors=True)
    except:
        pass
        
def pathExists( path):
    """Returns True if a path exists."""
    return os.path.isdir(path)
    
def fileExist( path):
    """Returns True if a file exist."""
    return os.path.isfile(path)
    
def mkdir( path, removeExisting = False):
    """ Create a full path, directory by directory"""
    #remove directiory if already exists
    if removeExisting:
        if pathExists(path):
            removePath(path)
                
    dirs = path.split("/")
    dir = ""
        
    for dirname in dirs:
        dir += dirname + "/"
        if not os.path.isdir(dir) and len(dir)>0:
            os.mkdir(dir)
            
def TimeFormat(value):
    #get days
    
    fDays = (value / 86400)
    tModDay = math.modf(fDays)
    Days = int(tModDay[1])
    decimalDays =tModDay[0]
    
    fTimeHour = decimalDays  * 24

     # Extract decimal from integer part
    tModHour = math.modf(fTimeHour)
    nHour = int(tModHour[1])
    fDecimalHour = tModHour[0]
    
    # Transform decimal in minutes
    fMinute = fDecimalHour*60
    # Again, extract the decimal and the integer part
    tModMinute = math.modf(fMinute)
    nMinute = int(tModMinute[1])
    fDecimalMinute = tModMinute[0]
    # Transform decimal in seconds
    fSecond = fDecimalMinute*60    
    # Again, extract the decimal and the integer part
    tModSecond = math.modf(fSecond)
    nSecond = int(tModSecond[1])
    
    
    output=''
    if Days >0:
        output = '%id' % Days

    if nHour >0:
        output+='%ih' % nHour
    
    if nMinute >0:
        output+='%im' % nMinute
    
    output+='%is' % nSecond
    
    return output


def fileSizeFormat( i):
    """
        Taken from jinja
        Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB,
        102 bytes, etc).
    """
    bytes = float(i)
    if bytes < 1024:
        return u"%d Byte%s" % (bytes, bytes != 1 and u's' or u'')
    elif bytes < 1024 * 1024:
        return u"%.1f KB" % (bytes / 1024)
    elif bytes < 1024 * 1024 * 1024:
        return u"%.1f MB" % (bytes / (1024 * 1024))
    else:
        return u"%.1f GB" % (bytes / (1024 * 1024 * 1024)) 

def openSelectDialog(title, filterName, pattern, selectMultiple = False):
        
    file_open = gtk.FileChooserDialog(title=title, 
                          action=gtk.FILE_CHOOSER_ACTION_OPEN, 
                          buttons=(gtk.STOCK_CANCEL, 
                          gtk.RESPONSE_CANCEL, 
                          gtk.STOCK_OPEN, gtk.RESPONSE_OK))
    filter = gtk.FileFilter()
    filter.set_name(filterName)
    filter.add_pattern(pattern)
    file_open.add_filter(filter)
    file_open.set_select_multiple(selectMultiple)
        
    result = ""
    path = ""
    filename = ""
    if file_open.run() == gtk.RESPONSE_OK:
        file_open.hide()
        results = file_open.get_filenames()
        file_open.destroy()
        return gtk.RESPONSE_OK, results
    else:
        file_open.destroy()
        return gtk.RESPONSE_CANCEL, []
        
def getFilePathFromUrl( uri):
     """ helper to get a useful path from a drop uri"""
     path = urllib.url2pathname(uri) # escape special chars
     path = path.strip('\r\n\x00') # remove \r\n and NULL
     # get the path to file
     if path.startswith('file:\\\\\\'): # windows
         path = path[8:] # 8 is len('file:///')
     elif path.startswith('file://'): # nautilus, rox
         path = path[7:] # 7 is len('file://')
     elif path.startswith('file:'): # xffm
         path = path[5:] # 5 is len('file:')
     return path          

class cursorManager:

	def __init__(self):
		self.window = None

	#procedure to change window cursor to ready cursor
	def setBusy(self, window_main = None, flag = True):
		""" Show a watch cursor if the app is busy for more than 0.3 sec.
		Furthermore provide a loop to handle user interface events """
		if window_main is None:
			return
		self.window = window_main.window
		if flag == True:
			try:
				self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
			except:
				print "An error occured changing cursor"
		else:
			self.window.set_cursor(None)
			while gtk.events_pending():
				gtk.main_iteration()

		return
    
class ContextMenu(gtk.Menu):
    def __init__(self, *args):
        gtk.Menu.__init__(self)
        self.menuItem = None
         
    def addMenuItem(self,menuName,actionFunction= None):
        
        if menuName == "-":
            self.menuItem = gtk.SeparatorMenuItem()
        else: 
            self.menuItem = gtk.MenuItem(menuName)
            if actionFunction is not None :
                self.menuItem.connect("activate", actionFunction)
        self.menuItem.show()
        self.append(self.menuItem)
        return
    
class SystemInfo:

    def __init__(self):
        self.distro = ''
        self.architecture = ''
        self.codename = ''
        self.release = ''
        self.read_release_info()
        
    def read_release_info(self):

        self.get_infos()
        self.architecture = self.__architecture()
   
    def get_infos(self):
  
        try:
            p = open('/etc/lsb-release','r')
            for line in p:
                if 'DISTRIB_ID' in line:
                    self.distro = line.split('=')[-1].replace('\n','').lower()
                elif 'DISTRIB_CODENAME' in line:
                    self.codename = line.split('=')[-1].replace('\n','').lower()
                elif 'DISTRIB_RELEASE' in line:
                    self.release = line.split('=')[-1].replace('\n','').lower()
            p.close()
        except:
            pass

    def __architecture(self):
        """
        Detect whether the architecture is x86/ppc/amd64
        """
        arch = os.uname()[-1]
        if arch in ('ppc', 'ppc64'):
            arch = 'powerpc'
        elif arch in ('sparc32','sparc64','sparc'):
            arch = 'sparc'
        elif arch =='x86_64':
            if self.distro in ('debian'):
                arch = 'ia64'
            else:
                arch = 'amd64'
        elif arch in ('i386','i686','i586','k7'):
            arch = 'i386'

        return arch
        
class RecursiveSearch:
    def __init__(self, directory, pattern="*"):
        self.stack = [directory]
        self.pattern = pattern
        self.files = []
        self.index = 0

    def __getitem__(self, index):
        while 1:
            try:
                file = self.files[self.index]
                self.index = self.index + 1
            except IndexError:
                # pop next directory from stack
                self.directory = self.stack.pop()
                self.files = os.listdir(self.directory)
                self.index = 0
            else:
                # got a filename
                fullname = os.path.join(self.directory, file)
                if os.path.isdir(fullname) and not os.path.islink(fullname):
                    self.stack.append(fullname)
                if fnmatch.fnmatch(file, self.pattern):
                    return fullname
                    
def compress(source, dest):
    dest_ext = '.bz2'
    arcname = os.path.basename (source)
    dest_name = '%s%s' % (dest, dest_ext)
    dest_path = os.path.join(dest, dest_name)

    input = bz2.compress(file(source, 'r').read())
    out = file(dest_path,'w')
    out.write(input)
    out.close()
    return dest_path
