# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import os
import random
import time

from autotest_lib.client.bin import test
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.audio import cras_utils

_STRESS_ITERATIONS = 100 # Total number of iterations.
_MAX_OPENED_TAB = 20     # Max number of tabs open and playing audio.
_RETAIN_TAB = 5          # In case we hit the _MAX_OPENED_TAB limit,
                         # close all except last 5 tabs.
_MAX_TABS_TO_OPEN = 10   # Max number of tabs can be opened in one iteration.
_CRASH_PATH = '/var/spool/crash'


class audio_ActiveStreamStress(test.test):
    """Verifies the active audio streams."""

    version = 1

    _active_stream_count = 0
    _existing_cras_reports = []
    _cr = None
    # TODO(rohitbm): add more(including video) file types and download them from gs://.
    _streams = ('audio.mp3', 'audio.wav', 'audio.m4a')
    _stream_index = 0
    _tab_count = 0

    def run_once(self):

        # Collect existing cras crash reports.
        self._existing_cras_reports = self.collect_cras_crash()

        with chrome.Chrome(init_network_controller=True) as self._cr:
            self._cr.browser.platform.SetHTTPServerDirectories(self.bindir)
            self.push_new_stream(self._cr.browser.tabs[0])
            # TODO(rohitbm): decide whether to perform verification on each
            # open/close or at end of the iteration.
            self.verify_active_streams()
            push_count = 0
            pop_count = 0

            # Stress test logic:
            # Test runs for n number of iterations. For one iteration,
            # a = random(10) tabs(streams) are created and
            # b = random(a) tabs are closed. If the next iteration finds that,
            # total number of opened tabs are more than _MAX_OPENED_TAB,
            # test will close (total opened tabs - 5) tabs.
            # This will balance number of opened tabs and will allow to close
            # tabs in a control manner.

            for count in xrange(1, _STRESS_ITERATIONS):
                if self._tab_count > _MAX_OPENED_TAB:
                     for i in xrange(1, (self._tab_count - _RETAIN_TAB)):
                         pop_count += 1
                         self.pop_stream()
                         logging.info('Total streams closed: %d', pop_count)
                random_tab = random.randint(1, 10)
                for i in xrange(1, random_tab):
                    push_count += 1
                    self.push_new_stream(self._cr.browser.tabs.New())
                    logging.info('Total new streams created: %d', push_count)
                time.sleep(5) # Delay for active streams to play.
                for i in xrange(1, random.randint(1, random_tab)):
                    pop_count += 1
                    self.pop_stream()
                    logging.info('Total streams closed: %d', pop_count)


    def get_stream_index(self):
        if self._stream_index == len(self._streams):
            # Reset the stream index if the index reached to the end.
            self._stream_index = 0
        return self._stream_index


    def push_new_stream(self, tab):
        """Starts next audio stream from self._streams list.

        @param tab: tab to open an audio stream.
        """
        self._tab_count += 1
        tab.Navigate(self._cr.browser.platform.http_server.UrlOf(
                    os.path.join(self.bindir,
                                 self._streams[self.get_stream_index()])))
        tab.ExecuteJavaScript(
                "document.getElementsByTagName('video')[0].loop=true")
        # TODO(rohitbm): add playback verification.
        self._stream_index += 1
        self._active_stream_count += 1
        time.sleep(1) # Adding a delay so cras can update the active count.
        self.verify_active_streams()


    def pop_stream(self):
        """Turns off the first available stream by closing the first tab."""
        if len(self._cr.browser.tabs) > 0:
            self._cr.browser.tabs[0].Close()
            self._tab_count -= 1
            self._active_stream_count -= 1
        time.sleep(1) # Adding delay so cras can update the active count.
        self.verify_active_streams()


    def verify_active_streams(self):
        """Verifies test active audio streams with cras active streams."""
        cras_stream_count = cras_utils.get_active_stream_count()
        if self._active_stream_count != cras_stream_count:
            cras_crash_reports = self.collect_cras_crash()
            new_reports = list(set(cras_crash_reports) -
                               set(self._existing_cras_reports))
            error_msg = ('Active stream count: %d is not matching with '
                         'cras active stream count: %d. '
                         'Number of cras crashes %d : %s' %
                         (self._active_stream_count, cras_stream_count,
                         len(new_reports), new_reports))
            raise error.TestError(error_msg)


    def collect_cras_crash(self):
        """Check for cras crashes.

        @return a list of cras crash reports found.
        """

        crash_reports = []
        if not os.path.isdir(_CRASH_PATH):
            logging.debug('No cras crash detected!')
        else:
            cras_reports = os.listdir(_CRASH_PATH)
            crash_reports = [report for report in cras_reports
                             if report.startswith('cras')]
        return crash_reports
