# 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 __future__ import unicode_literals

import getpass
import os
import sys
import time

from collections import namedtuple

# keep in sync with psutil os support, see psutil/__init__.py
if sys.platform.startswith("freebsd") or sys.platform.startswith("darwin") or sys.platform.startswith("win32") or sys.platform.startswith("linux"):
    try:
        import psutil
    except ImportError:
        psutil = None
else:
    psutil = None

from ..compilation.warnings import (
    WarningsCollector,
    WarningsDatabase,
)


BuildOutputResult = namedtuple('BuildOutputResult',
    ('warning', 'state_changed', 'for_display'))


class BuildMonitor(object):
    """Monitors the output of the build."""

    def __init__(self, topobjdir, warnings_path):
        """Create a new monitor.

        warnings_path is a path of a warnings database to use.
        """
        self._warnings_path = warnings_path

        self.tiers = []
        self.subtiers = []
        self.current_tier = None
        self.current_subtier = None
        self.current_tier_dirs = []
        self.current_tier_static_dirs = []
        self.current_subtier_dirs = []
        self.current_tier_dir = None
        self.current_tier_dir_index = 0

        self.warnings_database = WarningsDatabase()
        if os.path.exists(warnings_path):
            try:
                self.warnings_database.load_from_file(warnings_path)
            except ValueError:
                os.remove(warnings_path)

        self._warnings_collector = WarningsCollector(
            database=self.warnings_database, objdir=topobjdir)

    def start(self):
        """Record the start of the build."""
        self.start_time = time.time()
        self._finder_start_cpu = self._get_finder_cpu_usage()

    def on_line(self, line):
        """Consume a line of output from the build system.

        This will parse the line for state and determine whether more action is
        needed.

        Returns a BuildOutputResult instance.

        In this named tuple, warning will be an object describing a new parsed
        warning. Otherwise it will be None.

        state_changed indicates whether the build system changed state with
        this line. If the build system changed state, the caller may want to
        query this instance for the current state in order to update UI, etc.

        for_display is a boolean indicating whether the line is relevant to the
        user. This is typically used to filter whether the line should be
        presented to the user.
        """
        if line.startswith('BUILDSTATUS'):
            args = line.split()[1:]

            action = args.pop(0)
            update_needed = True

            if action == 'TIERS':
                self.tiers = args
                update_needed = False
            elif action == 'SUBTIERS':
                self.subtiers = args
                update_needed = False
            elif action == 'STATICDIRS':
                self.current_tier_static_dirs = args
                update_needed = False
            elif action == 'DIRS':
                self.current_tier_dirs = args
                update_needed = False
            elif action == 'TIER_START':
                assert len(args) == 1
                self.current_tier = args[0]
                self.current_subtier = None
                self.current_tier_dirs = []
                self.current_tier_dir = None
            elif action == 'TIER_FINISH':
                assert len(args) == 1
                assert args[0] == self.current_tier
            elif action == 'SUBTIER_START':
                assert len(args) == 2
                tier, subtier = args
                assert tier == self.current_tier
                self.current_subtier = subtier
                if subtier == 'static':
                    self.current_subtier_dirs = self.current_tier_static_dirs
                else:
                    self.current_subtier_dirs = self.current_tier_dirs
                self.current_tier_dir_index = 0
            elif action == 'SUBTIER_FINISH':
                assert len(args) == 2
                tier, subtier = args
                assert tier == self.current_tier
                assert subtier == self.current_subtier
            elif action == 'TIERDIR_START':
                assert len(args) == 1
                self.current_tier_dir = args[0]
                self.current_tier_dir_index += 1
            elif action == 'TIERDIR_FINISH':
                assert len(args) == 1
                assert self.current_tier_dir == args[0]
            else:
                raise Exception('Unknown build status: %s' % action)

            return BuildOutputResult(None, update_needed, False)

        warning = None

        try:
            warning = self._warnings_collector.process_line(line)
        except:
            pass

        return BuildOutputResult(warning, False, True)

    def finish(self):
        """Record the end of the build."""
        self.end_time = time.time()
        self._finder_end_cpu = self._get_finder_cpu_usage()
        self.elapsed = self.end_time - self.start_time

        self.warnings_database.prune()
        self.warnings_database.save_to_file(self._warnings_path)

    def _get_finder_cpu_usage(self):
        """Obtain the CPU usage of the Finder app on OS X.

        This is used to detect high CPU usage.
        """
        if not sys.platform.startswith('darwin'):
            return None

        if not psutil:
            return None

        for proc in psutil.process_iter():
            if proc.name != 'Finder':
                continue

            if proc.username != getpass.getuser():
                continue

            # Try to isolate system finder as opposed to other "Finder"
            # processes.
            if not proc.exe.endswith('CoreServices/Finder.app/Contents/MacOS/Finder'):
                continue

            return proc.get_cpu_times()

        return None

    def have_high_finder_usage(self):
        """Determine whether there was high Finder CPU usage during the build.

        Returns True if there was high Finder CPU usage, False if there wasn't,
        or None if there is nothing to report.
        """
        if not self._finder_start_cpu:
            return None, None

        # We only measure if the measured range is sufficiently long.
        if self.elapsed < 15:
            return None, None

        if not self._finder_end_cpu:
            return None, None

        start = self._finder_start_cpu
        end = self._finder_end_cpu

        start_total = start.user + start.system
        end_total = end.user + end.system

        cpu_seconds = end_total - start_total

        # If Finder used more than 25% of 1 core during the build, report an
        # error.
        finder_percent = cpu_seconds / self.elapsed * 100

        return finder_percent > 25, finder_percent
