from ConfigParser import (
    ConfigParser,
    RawConfigParser
)
import datetime
import os
import posixpath
import re
import shutil
import socket
import subprocess
import tempfile
import time
import traceback

from mozdevice import DMError
from mozprocess import ProcessHandler

class Device(object):
    connected = False

    def __init__(self, app_ctx, logdir=None, serial=None, restore=True):
        self.app_ctx = app_ctx
        self.dm = self.app_ctx.dm
        self.restore = restore
        self.serial = serial
        self.logdir = logdir
        self.added_files = set()
        self.backup_files = set()

    @property
    def remote_profiles(self):
        """
        A list of remote profiles on the device.
        """
        remote_ini = self.app_ctx.remote_profiles_ini
        if not self.dm.fileExists(remote_ini):
            raise IOError("Remote file '%s' not found" % remote_ini)

        local_ini = tempfile.NamedTemporaryFile()
        self.dm.getFile(remote_ini, local_ini.name)
        cfg = ConfigParser()
        cfg.read(local_ini.name)

        profiles = []
        for section in cfg.sections():
            if cfg.has_option(section, 'Path'):
                if cfg.has_option(section, 'IsRelative') and cfg.getint(section, 'IsRelative'):
                    profiles.append(posixpath.join(posixpath.dirname(remote_ini), \
                                    cfg.get(section, 'Path')))
                else:
                    profiles.append(cfg.get(section, 'Path'))
        return profiles

    def pull_minidumps(self):
        """
        Saves any minidumps found in the remote profile on the local filesystem.

        :returns: Path to directory containing the dumps.
        """
        remote_dump_dir = posixpath.join(self.app_ctx.remote_profile, 'minidumps')
        local_dump_dir = tempfile.mkdtemp()
        self.dm.getDirectory(remote_dump_dir, local_dump_dir)
        if os.listdir(local_dump_dir):
            for f in self.dm.listFiles(remote_dump_dir):
                self.dm.removeFile(posixpath.join(remote_dump_dir, f))
        return local_dump_dir

    def setup_profile(self, profile):
        """
        Copy profile to the device and update the remote profiles.ini
        to point to the new profile.

        :param profile: mozprofile object to copy over.
        """
        self.dm.remount()

        if self.dm.dirExists(self.app_ctx.remote_profile):
            self.dm.shellCheckOutput(['rm', '-r', self.app_ctx.remote_profile])

        self.dm.pushDir(profile.profile, self.app_ctx.remote_profile)

        timeout = 5 # seconds
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            if self.dm.fileExists(self.app_ctx.remote_profiles_ini):
                break
            time.sleep(1)
        else:
            print "timed out waiting for profiles.ini"

        local_profiles_ini = tempfile.NamedTemporaryFile()
        self.dm.getFile(self.app_ctx.remote_profiles_ini, local_profiles_ini.name)

        config = ProfileConfigParser()
        config.read(local_profiles_ini.name)
        for section in config.sections():
            if 'Profile' in section:
                config.set(section, 'IsRelative', 0)
                config.set(section, 'Path', self.app_ctx.remote_profile)

        new_profiles_ini = tempfile.NamedTemporaryFile()
        config.write(open(new_profiles_ini.name, 'w'))

        self.backup_file(self.app_ctx.remote_profiles_ini)
        self.dm.pushFile(new_profiles_ini.name, self.app_ctx.remote_profiles_ini)

        # Ideally all applications would read the profile the same way, but in practice
        # this isn't true. Perform application specific profile-related setup if necessary.
        if hasattr(self.app_ctx, 'setup_profile'):
            for remote_path in self.app_ctx.remote_backup_files:
                self.backup_file(remote_path)
            self.app_ctx.setup_profile(profile)

    def _get_online_devices(self):
        return [d[0] for d in self.dm.devices() if d[1] != 'offline' if not d[0].startswith('emulator')]

    def connect(self):
        """
        Connects to a running device. If no serial was specified in the
        constructor, defaults to the first entry in `adb devices`.
        """
        if self.connected:
            return

        if self.serial:
            serial = self.serial
        else:
            online_devices = self._get_online_devices()
            if not online_devices:
                raise IOError("No devices connected. Ensure the device is on and remote debugging via adb is enabled in the settings.")
            serial = online_devices[0]

        self.dm._deviceSerial = serial
        self.dm.connect()
        self.connected = True

        if self.logdir:
            # save logcat
            logcat_log = os.path.join(self.logdir, '%s.log' % serial)
            if os.path.isfile(logcat_log):
                self._rotate_log(logcat_log)
            logcat_args = [self.app_ctx.adb, '-s', '%s' % serial,
                           'logcat', '-v', 'time', '-b', 'main', '-b', 'radio']
            self.logcat_proc = ProcessHandler(logcat_args, logfile=logcat_log)
            self.logcat_proc.run()

    def reboot(self):
        """
        Reboots the device via adb.
        """
        self.dm.reboot(wait=True)

    def install_busybox(self, busybox):
        """
        Installs busybox on the device.

        :param busybox: Path to busybox binary to install.
        """
        self.dm.remount()
        print 'pushing %s' % self.app_ctx.remote_busybox
        self.dm.pushFile(busybox, self.app_ctx.remote_busybox, retryLimit=10)
        # TODO for some reason using dm.shellCheckOutput doesn't work,
        #      while calling adb shell directly does.
        args = [self.app_ctx.adb, '-s', self.dm._deviceSerial,
                'shell', 'cd /system/bin; chmod 555 busybox;' \
                'for x in `./busybox --list`; do ln -s ./busybox $x; done']
        adb = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        adb.wait()
        self.dm._verifyZip()

    def setup_port_forwarding(self, local_port=None, remote_port=2828):
        """
        Set up TCP port forwarding to the specified port on the device,
        using any availble local port (if none specified), and return the local port.

        :param local_port: The local port to forward from, if unspecified a
                           random port is chosen.
        :param remote_port: The remote port to forward to, defaults to 2828.
        :returns: The local_port being forwarded.
        """
        if not local_port:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.bind(("",0))
            local_port = s.getsockname()[1]
            s.close()

        self.dm.forward('tcp:%d' % int(local_port), 'tcp:%d' % int(remote_port))
        return local_port

    def wait_for_net(self):
        active = False
        time_out = 0
        while not active and time_out < 40:
            proc = subprocess.Popen([self.app_ctx.adb, 'shell', '/system/bin/netcfg'], stdout=subprocess.PIPE)
            proc.stdout.readline() # ignore first line
            line = proc.stdout.readline()
            while line != "":
                if (re.search(r'UP\s+[1-9]\d{0,2}\.\d{1,3}\.\d{1,3}\.\d{1,3}', line)):
                    active = True
                    break
                line = proc.stdout.readline()
            time_out += 1
            time.sleep(1)
        return active

    def wait_for_port(self, port, timeout=300):
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect(('localhost', port))
                data = sock.recv(16)
                sock.close()
                if ':' in data:
                    return True
            except:
                traceback.print_exc()
            time.sleep(1)
        return False

    def backup_file(self, remote_path):
        if not self.restore:
            return

        if self.dm.fileExists(remote_path) or self.dm.dirExists(remote_path):
            self.dm.copyTree(remote_path, '%s.orig' % remote_path)
            self.backup_files.add(remote_path)
        else:
            self.added_files.add(remote_path)

    def cleanup(self):
        """
        Cleanup the device.
        """
        if not self.restore:
            return

        try:
            self.dm._verifyDevice()
        except DMError:
            return

        self.dm.remount()
        # Restore the original profile
        for added_file in self.added_files:
            self.dm.removeFile(added_file)

        for backup_file in self.backup_files:
            if self.dm.fileExists('%s.orig' % backup_file) or self.dm.dirExists('%s.orig' % backup_file):
                self.dm.moveTree('%s.orig' % backup_file, backup_file)

        # Perform application specific profile cleanup if necessary
        if hasattr(self.app_ctx, 'cleanup_profile'):
            self.app_ctx.cleanup_profile()

        # Remove the test profile
        self.dm.removeDir(self.app_ctx.remote_profile)

    def _rotate_log(self, srclog, index=1):
        """
        Rotate a logfile, by recursively rotating logs further in the sequence,
        deleting the last file if necessary.
        """
        basename = os.path.basename(srclog)
        basename = basename[:-len('.log')]
        if index > 1:
            basename = basename[:-len('.1')]
        basename = '%s.%d.log' % (basename, index)

        destlog = os.path.join(self.logdir, basename)
        if os.path.isfile(destlog):
            if index == 3:
                os.remove(destlog)
            else:
                self._rotate_log(destlog, index+1)
        shutil.move(srclog, destlog)



class ProfileConfigParser(RawConfigParser):
    """
    Class to create profiles.ini config files

    Subclass of RawConfigParser that outputs .ini files in the exact
    format expected for profiles.ini, which is slightly different
    than the default format.
    """

    def optionxform(self, optionstr):
        return optionstr

    def write(self, fp):
        if self._defaults:
            fp.write("[%s]\n" % ConfigParser.DEFAULTSECT)
            for (key, value) in self._defaults.items():
                fp.write("%s=%s\n" % (key, str(value).replace('\n', '\n\t')))
            fp.write("\n")
        for section in self._sections:
            fp.write("[%s]\n" % section)
            for (key, value) in self._sections[section].items():
                if key == "__name__":
                    continue
                if (value is not None) or (self._optcre == self.OPTCRE):
                    key = "=".join((key, str(value).replace('\n', '\n\t')))
                fp.write("%s\n" % (key))
            fp.write("\n")

