#!/usr/bin/python3

# Copyright (C) 2009 Canonical Ltd.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# 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/>.

import gettext
import logging, logging.handlers
import os
import subprocess
import sys

# Padding for the kernel and initramfs, in megabytes
PADDING = 30
(CAN_USE,     # Obvious.
 CANNOT_USE,  # The partition or disk is too small for the source image.
 NEED_SPACE,  # There is not enough free space, but there could be.
 NEED_FORMAT, # The device has the wrong filesystem type, or the source is a
              # disk image.
) = list(range(4))
SOURCE_CD, SOURCE_ISO, SOURCE_IMG = list(range(3))
MAX_LOG_SIZE = 1024 * 1024 * 1
MAX_LOG_BACKUP = 0

# TODO xnox 20121109 should not hard-code timeouts, instead should
# do async dbus calls with a qt or glib main loop running.
MAX_DBUS_TIMEOUT = 2147483

if sys.version >= '3':
    text_type = str

    def callable(obj):
        import collections
        return isinstance(obj, collections.abc.Callable)
else:
    text_type = unicode

    callable = callable

def setup_gettext(localedir='/usr/share/locale'):
    kwargs = {}
    if sys.version < '3':
        kwargs['unicode'] = True
    gettext.install('usbcreator', localedir=localedir, **kwargs)

def setup_logging():
    log = logging.getLogger('')
    # usb-creator used to write ~/.usb-creator.log as root (whoops!), so lets
    # use a different name here. -- ev
    # new location so let's go back to original name =) -- xnox
    cache_dir = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
    log_file = os.path.join(cache_dir, 'usb-creator.log')
    handler = None
    try:
        handler = logging.handlers.RotatingFileHandler(log_file,
                     maxBytes=MAX_LOG_SIZE, backupCount=MAX_LOG_BACKUP)
    except IOError:
        logging.exception('Could not set up file logging:')
    if handler:
        formatter = logging.Formatter('usb-creator %(asctime)s (%(levelname)s)'
                                      ' %(filename)s:%(lineno)d: %(message)s')
        handler.setFormatter(formatter)
        handler.setLevel(logging.DEBUG)
        log.addHandler(handler)
    log.setLevel(logging.DEBUG)

def format_size(size):
    """Format a partition size."""
    # Taken from ubiquity's ubiquity/misc.py
    # TODO evand 2009-07-28: Localized size formatting.
    if size < 1024:
        unit = 'B'
        factor = 1
    elif size < 1024 * 1024:
        unit = 'kB'
        factor = 1024
    elif size < 1024 * 1024 * 1024:
        unit = 'MB'
        factor = 1024 * 1024
    elif size < 1024 * 1024 * 1024 * 1024:
        unit = 'GB'
        factor = 1024 * 1024 * 1024
    else:
        unit = 'TB'
        factor = 1024 * 1024 * 1024 * 1024
    return '%.1f %s' % (float(size) / factor, unit)

def format_mb_size(size):
    if size < 1024:
        unit = 'MB'
        factor = 1
    elif size < 1024 * 1024:
        unit = 'GB'
        factor = 1024
    elif size < 1024 * 1024 * 1024:
        unit = 'TB'
        factor = 1024 * 1024
    return '%.1f %s' % (float(size) / factor, unit)

class USBCreatorProcessException(Exception):
    pass

def popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
          stdin=subprocess.PIPE):
    logging.debug(str(cmd))
    startupinfo = None
    process = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, stdin=stdin,
                               universal_newlines=True,
                               startupinfo=startupinfo)
    out, err = process.communicate()
    if process.returncode is None:
        process.wait()
    elif process.returncode != 0:
        raise USBCreatorProcessException(err)
    return out

# Taken from ubiquity.
def find_on_path(command):
    """Is command on the executable search path?"""
    if 'PATH' not in os.environ:
        return False
    path = os.environ['PATH']
    for element in path.split(os.pathsep):
        if not element:
            continue
        filename = os.path.join(element, command)
        if os.path.isfile(filename) and os.access(filename, os.X_OK):
            return True
    return False

def prepend_path(directory):
    if 'PATH' in os.environ and os.environ['PATH'] != '':
        os.environ['PATH'] = '%s:%s' % (directory, os.environ['PATH'])
    else:
        os.environ['PATH'] = directory

def sane_path():
    elements = os.environ.get('PATH', '').split(os.pathsep)
    for element in ('/bin', '/sbin', '/usr/bin', '/usr/sbin'):
        if element not in elements:
            prepend_path(element)
