# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

from optparse import OptionParser
import os
import shutil
import subprocess
import sys
import tarfile
import time
import zipfile

import mozfile
import mozinfo

try:
    import pefile
    has_pefile = True
except ImportError:
    has_pefile = False

if mozinfo.isMac:
    from plistlib import readPlist


TIMEOUT_UNINSTALL = 60


class InstallError(Exception):
    """Thrown when installation fails. Includes traceback if available."""


class InvalidBinary(Exception):
    """Thrown when the binary cannot be found after the installation."""


class InvalidSource(Exception):
    """Thrown when the specified source is not a recognized file type.

    Supported types:
    Linux:   tar.gz, tar.bz2
    Mac:     dmg
    Windows: zip, exe

    """


class UninstallError(Exception):
    """Thrown when uninstallation fails. Includes traceback if available."""


def get_binary(path, app_name):
    """Find the binary in the specified path, and return its path. If binary is
    not found throw an InvalidBinary exception.

    :param path: Path within to search for the binary
    :param app_name: Application binary without file extension to look for
    """
    binary = None

    # On OS X we can get the real binary from the app bundle
    if mozinfo.isMac:
        plist = '%s/Contents/Info.plist' % path
        if not os.path.isfile(plist):
            raise InvalidBinary('%s/Contents/Info.plist not found' % path)

        binary = os.path.join(path, 'Contents/MacOS/',
                              readPlist(plist)['CFBundleExecutable'])

    else:
        app_name = app_name.lower()

        if mozinfo.isWin:
            app_name = app_name + '.exe'

        for root, dirs, files in os.walk(path):
            for filename in files:
                # os.access evaluates to False for some reason, so not using it
                if filename.lower() == app_name:
                    binary = os.path.realpath(os.path.join(root, filename))
                    break

    if not binary:
        # The expected binary has not been found.
        raise InvalidBinary('"%s" does not contain a valid binary.' % path)

    return binary


def install(src, dest):
    """Install a zip, exe, tar.gz, tar.bz2 or dmg file, and return the path of
    the installation folder.

    :param src: Path to the install file
    :param dest: Path to install to (to ensure we do not overwrite any existent
                 files the folder should not exist yet)
    """
    src = os.path.realpath(src)
    dest = os.path.realpath(dest)

    if not is_installer(src):
        raise InvalidSource(src + ' is not valid installer file.')

    did_we_create = False
    if not os.path.exists(dest):
        did_we_create = True
        os.makedirs(dest)

    trbk = None
    try:
        install_dir = None
        if src.lower().endswith('.dmg'):
            install_dir = _install_dmg(src, dest)
        elif src.lower().endswith('.exe'):
            install_dir = _install_exe(src, dest)
        elif zipfile.is_zipfile(src) or tarfile.is_tarfile(src):
            install_dir = mozfile.extract(src, dest)[0]

        return install_dir

    except:
        cls, exc, trbk = sys.exc_info()
        if did_we_create:
            try:
                # try to uninstall this properly
                uninstall(dest)
            except:
                # uninstall may fail, let's just try to clean the folder
                # in this case
                try:
                    mozfile.remove(dest)
                except:
                    pass
        if issubclass(cls, Exception):
            error = InstallError('Failed to install "%s (%s)"' % (src, str(exc)))
            raise InstallError, error, trbk
        # any other kind of exception like KeyboardInterrupt is just re-raised.
        raise cls, exc, trbk

    finally:
        # trbk won't get GC'ed due to circular reference
        # http://docs.python.org/library/sys.html#sys.exc_info
        del trbk


def is_installer(src):
    """Tests if the given file is a valid installer package.

    Supported types:
    Linux:   tar.gz, tar.bz2
    Mac:     dmg
    Windows: zip, exe

    On Windows pefile will be used to determine if the executable is the
    right type, if it is installed on the system.

    :param src: Path to the install file.
    """
    src = os.path.realpath(src)

    if not os.path.isfile(src):
        return False

    if mozinfo.isLinux:
        return tarfile.is_tarfile(src)
    elif mozinfo.isMac:
        return src.lower().endswith('.dmg')
    elif mozinfo.isWin:
        if zipfile.is_zipfile(src):
            return True

        if os.access(src, os.X_OK) and src.lower().endswith('.exe'):
            if has_pefile:
                # try to determine if binary is actually a gecko installer
                pe_data = pefile.PE(src)
                data = {}
                for info in getattr(pe_data, 'FileInfo', []):
                    if info.Key == 'StringFileInfo':
                        for string in info.StringTable:
                            data.update(string.entries)
                return 'BuildID' not in data
            else:
                # pefile not available, just assume a proper binary was passed in
                return True

        return False


def uninstall(install_folder):
    """Uninstalls the application in the specified path. If it has been
    installed via an installer on Windows, use the uninstaller first.

    :param install_folder: Path of the installation folder

    """
    install_folder = os.path.realpath(install_folder)
    assert os.path.isdir(install_folder), \
        'installation folder "%s" exists.' % install_folder

    # On Windows we have to use the uninstaller. If it's not available fallback
    # to the directory removal code
    if mozinfo.isWin:
        uninstall_folder = '%s\uninstall' % install_folder
        log_file = '%s\uninstall.log' % uninstall_folder

        if os.path.isfile(log_file):
            trbk = None
            try:
                cmdArgs = ['%s\uninstall\helper.exe' % install_folder, '/S']
                result = subprocess.call(cmdArgs)
                if result is not 0:
                    raise Exception('Execution of uninstaller failed.')

                # The uninstaller spawns another process so the subprocess call
                # returns immediately. We have to wait until the uninstall
                # folder has been removed or until we run into a timeout.
                end_time = time.time() + TIMEOUT_UNINSTALL
                while os.path.exists(uninstall_folder):
                    time.sleep(1)

                    if time.time() > end_time:
                        raise Exception('Failure removing uninstall folder.')

            except Exception, ex:
                cls, exc, trbk = sys.exc_info()
                error = UninstallError('Failed to uninstall %s (%s)' % (install_folder, str(ex)))
                raise UninstallError, error, trbk

            finally:
                # trbk won't get GC'ed due to circular reference
                # http://docs.python.org/library/sys.html#sys.exc_info
                del trbk

    # Ensure that we remove any trace of the installation. Even the uninstaller
    # on Windows leaves files behind we have to explicitely remove.
    mozfile.remove(install_folder)


def _install_dmg(src, dest):
    """Extract a dmg file into the destination folder and return the
    application folder.

    src -- DMG image which has to be extracted
    dest -- the path to extract to

    """
    try:
        proc = subprocess.Popen('hdiutil attach -nobrowse -noautoopen "%s"' % src,
                                shell=True,
                                stdout=subprocess.PIPE)

        for data in proc.communicate()[0].split():
            if data.find('/Volumes/') != -1:
                appDir = data
                break

        for appFile in os.listdir(appDir):
            if appFile.endswith('.app'):
                appName = appFile
                break

        mounted_path = os.path.join(appDir, appName)

        dest = os.path.join(dest, appName)

        # copytree() would fail if dest already exists.
        if os.path.exists(dest):
            raise InstallError('App bundle "%s" already exists.' % dest)

        shutil.copytree(mounted_path, dest, False)

    finally:
        subprocess.call('hdiutil detach %s -quiet' % appDir,
                        shell=True)

    return dest


def _install_exe(src, dest):
    """Run the MSI installer to silently install the application into the
    destination folder. Return the folder path.

    Arguments:
    src -- MSI installer to be executed
    dest -- the path to install to

    """
    # The installer doesn't automatically create a sub folder. Lets guess the
    # best name from the src file name
    filename = os.path.basename(src)
    dest = os.path.join(dest, filename.split('.')[0])

    # possibly gets around UAC in vista (still need to run as administrator)
    os.environ['__compat_layer'] = 'RunAsInvoker'
    cmd = '"%s" /extractdir=%s' % (src, os.path.realpath(dest))

    # As long as we support Python 2.4 check_call will not be available.
    result = subprocess.call(cmd)

    if result is not 0:
        raise Exception('Execution of installer failed.')

    return dest


def install_cli(argv=sys.argv[1:]):
    parser = OptionParser(usage="usage: %prog [options] installer")
    parser.add_option('-d', '--destination',
                      dest='dest',
                      default=os.getcwd(),
                      help='Directory to install application into. '
                           '[default: "%default"]')
    parser.add_option('--app', dest='app',
                      default='firefox',
                      help='Application being installed. [default: %default]')

    (options, args) = parser.parse_args(argv)
    if not len(args) == 1:
        parser.error('An installer file has to be specified.')

    src = args[0]

    # Run it
    if os.path.isdir(src):
        binary = get_binary(src, app_name=options.app)
    else:
        install_path = install(src, options.dest)
        binary = get_binary(install_path, app_name=options.app)

    print binary


def uninstall_cli(argv=sys.argv[1:]):
    parser = OptionParser(usage="usage: %prog install_path")

    (options, args) = parser.parse_args(argv)
    if not len(args) == 1:
        parser.error('An installation path has to be specified.')

    # Run it
    uninstall(argv[0])

