# Copyright 2016 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.

"""Resource manager to access the ARC-related functionality."""

import logging
import os
import pipes
import time

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import arc
from autotest_lib.client.cros.multimedia import arc_resource_common
from autotest_lib.client.cros.input_playback import input_playback


def set_tag(tag):
    """Sets a tag file.

    @param tag: Path to the tag file.

    """
    open(tag, 'w').close()


def tag_exists(tag):
    """Checks if a tag exists.

    @param tag: Path to the tag file.

    """
    return os.path.exists(tag)


class ArcMicrophoneResourceException(Exception):
    """Exceptions in ArcResource."""
    pass


class ArcMicrophoneResource(object):
    """Class to manage microphone app in container."""
    _MICROPHONE_ACTIVITY = 'org.chromium.arc.testapp.microphone/.MainActivity'
    _MICROPHONE_PACKAGE = 'org.chromium.arc.testapp.microphone'
    _MICROPHONE_RECORD_PATH = '/storage/emulated/0/recorded.amr-nb'
    _MICROPHONE_PERMISSIONS = ['RECORD_AUDIO', 'WRITE_EXTERNAL_STORAGE',
                               'READ_EXTERNAL_STORAGE']

    def __init__(self):
        """Initializes a ArcMicrophoneResource."""
        self._mic_app_start_time = None


    def start_microphone_app(self):
        """Starts microphone app to start recording.

        Starts microphone app. The app starts recorder itself after start up.

        @raises: ArcMicrophoneResourceException if microphone app is not ready
                 yet.

        """
        if not tag_exists(arc_resource_common.MicrophoneProps.READY_TAG_FILE):
            raise ArcMicrophoneResourceException(
                    'Microphone app is not ready yet.')

        if self._mic_app_start_time:
            raise ArcMicrophoneResourceException(
                    'Microphone app is already started.')

        # In case the permissions are cleared, set the permission again before
        # each start of the app.
        self._set_permission()
        self._start_app()
        self._mic_app_start_time = time.time()


    def stop_microphone_app(self, dest_path):
        """Stops microphone app and gets recorded audio file from container.

        Stops microphone app.
        Copies the recorded file from container to Cros device.
        Deletes the recorded file in container.

        @param dest_path: Destination path of the recorded file on Cros device.

        @raises: ArcMicrophoneResourceException if microphone app is not started
                 yet or is still recording.

        """
        if not self._mic_app_start_time:
            raise ArcMicrophoneResourceException(
                    'Recording is not started yet')

        if self._is_recording():
            raise ArcMicrophoneResourceException('Still recording')

        self._stop_app()
        self._get_file(dest_path)
        self._delete_file()

        self._mic_app_start_time = None


    def _is_recording(self):
        """Checks if microphone app is recording audio.

        We use the time stamp of app start up time to determine if app is still
        recording audio.

        @returns: True if microphone app is recording, False otherwise.

        """
        if not self._mic_app_start_time:
            return False

        return (time.time() - self._mic_app_start_time <
                (arc_resource_common.MicrophoneProps.RECORD_SECS +
                 arc_resource_common.MicrophoneProps.RECORD_FUZZ_SECS))


    def _set_permission(self):
        """Grants permissions to microphone app."""
        for permission in self._MICROPHONE_PERMISSIONS:
            arc.adb_shell('pm grant %s android.permission.%s' % (
                    pipes.quote(self._MICROPHONE_PACKAGE),
                    pipes.quote(permission)))


    def _start_app(self):
        """Starts microphone app."""
        arc.adb_shell('am start -W %s' % pipes.quote(self._MICROPHONE_ACTIVITY))


    def _stop_app(self):
        """Stops microphone app.

        Stops the microphone app process.

        """
        arc.adb_shell(
                'am force-stop %s' % pipes.quote(self._MICROPHONE_PACKAGE))


    def _get_file(self, dest_path):
        """Gets recorded audio file from container.

        Copies the recorded file from container to Cros device.

        @dest_path: Destination path of the recorded file on Cros device.

        """
        arc.adb_cmd('pull %s %s' % (pipes.quote(self._MICROPHONE_RECORD_PATH),
                                    pipes.quote(dest_path)))


    def _delete_file(self):
        """Removes the recorded file in container."""
        arc.adb_shell('rm %s' % pipes.quote(self._MICROPHONE_RECORD_PATH))


class ArcPlayMusicResourceException(Exception):
    """Exceptions in ArcPlayMusicResource."""
    pass


class ArcPlayMusicResource(object):
    """Class to manage Play Music app in container."""
    _PLAYMUSIC_PACKAGE = 'com.google.android.music'
    _PLAYMUSIC_FILE_FOLDER = '/storage/emulated/0/'
    _PLAYMUSIC_PERMISSIONS = ['WRITE_EXTERNAL_STORAGE', 'READ_EXTERNAL_STORAGE']
    _PLAYMUSIC_ACTIVITY = '.AudioPreview'
    _KEYCODE_MEDIA_STOP = 86

    def __init__(self):
        """Initializes an ArcPlayMusicResource."""
        self._files_pushed = []


    def set_playback_file(self, file_path):
        """Copies file into container.

        @param file_path: Path to the file to play on Cros host.

        @returns: Path to the file in container.

        """
        file_name = os.path.basename(file_path)
        dest_path = os.path.join(self._PLAYMUSIC_FILE_FOLDER, file_name)

        # pipes.quote is deprecated in 2.7 (but still available).
        # It should be replaced by shlex.quote in python 3.3.
        arc.adb_cmd('push %s %s' % (pipes.quote(file_path),
                                    pipes.quote(dest_path)))

        self._files_pushed.append(dest_path)

        return dest_path


    def start_playback(self, dest_path):
        """Starts Play Music app to play an audio file.

        @param dest_path: The file path in container.

        @raises ArcPlayMusicResourceException: Play Music app is not ready or
                                               playback file is not set yet.

        """
        if not tag_exists(arc_resource_common.PlayMusicProps.READY_TAG_FILE):
            raise ArcPlayMusicResourceException(
                    'Play Music app is not ready yet.')

        if dest_path not in self._files_pushed:
            raise ArcPlayMusicResourceException(
                    'Playback file is not set yet')

        # In case the permissions are cleared, set the permission again before
        # each start of the app.
        self._set_permission()
        self._start_app(dest_path)


    def _set_permission(self):
        """Grants permissions to Play Music app."""
        for permission in self._PLAYMUSIC_PERMISSIONS:
            arc.adb_shell('pm grant %s android.permission.%s' % (
                    pipes.quote(self._PLAYMUSIC_PACKAGE),
                    pipes.quote(permission)))


    def _start_app(self, dest_path):
        """Starts Play Music app playing an audio file.

        @param dest_path: Path to the file to play in container.

        """
        ext = os.path.splitext(dest_path)[1]
        command = ('am start -a android.intent.action.VIEW'
                   ' -d "file://%s" -t "audio/%s"'
                   ' -n "%s/%s"'% (
                          pipes.quote(dest_path), pipes.quote(ext),
                          pipes.quote(self._PLAYMUSIC_PACKAGE),
                          pipes.quote(self._PLAYMUSIC_ACTIVITY)))
        logging.debug(command)
        arc.adb_shell(command)


    def stop_playback(self):
        """Stops Play Music app.

        Stops the Play Music app by media key event.

        """
        arc.send_keycode(self._KEYCODE_MEDIA_STOP)


    def cleanup(self):
        """Removes the files to play in container."""
        for path in self._files_pushed:
            arc.adb_shell('rm %s' % pipes.quote(path))
        self._files_pushed = []


class ArcPlayVideoResourceException(Exception):
    """Exceptions in ArcPlayVideoResource."""
    pass


class ArcPlayVideoResource(object):
    """Class to manage Play Video app in container."""
    _PLAYVIDEO_PACKAGE = 'org.chromium.arc.testapp.video'
    _PLAYVIDEO_ACTIVITY = 'org.chromium.arc.testapp.video/.MainActivity'
    _PLAYVIDEO_EXIT_TAG = "/mnt/sdcard/ArcVideoTest.tag"
    _PLAYVIDEO_FILE_FOLDER = '/storage/emulated/0/'
    _PLAYVIDEO_PERMISSIONS = ['WRITE_EXTERNAL_STORAGE', 'READ_EXTERNAL_STORAGE']
    _KEYCODE_MEDIA_PLAY = 126
    _KEYCODE_MEDIA_PAUSE = 127
    _KEYCODE_MEDIA_STOP = 86

    def __init__(self):
        """Initializes an ArcPlayVideoResource."""
        self._files_pushed = []


    def prepare_playback(self, file_path, fullscreen=True):
        """Copies file into the container and starts the video player app.

        @param file_path: Path to the file to play on Cros host.
        @param fullscreen: Plays the video in fullscreen.

        """
        if not tag_exists(arc_resource_common.PlayVideoProps.READY_TAG_FILE):
            raise ArcPlayVideoResourceException(
                    'Play Video app is not ready yet.')
        file_name = os.path.basename(file_path)
        dest_path = os.path.join(self._PLAYVIDEO_FILE_FOLDER, file_name)

        # pipes.quote is deprecated in 2.7 (but still available).
        # It should be replaced by shlex.quote in python 3.3.
        arc.adb_cmd('push %s %s' % (pipes.quote(file_path),
                                    pipes.quote(dest_path)))

        # In case the permissions are cleared, set the permission again before
        # each start of the app.
        self._set_permission()
        self._start_app(dest_path)
        if fullscreen:
            self.set_fullscreen()


    def set_fullscreen(self):
        """Sends F4 keyevent to set fullscreen."""
        with input_playback.InputPlayback() as input_player:
            input_player.emulate(input_type='keyboard')
            input_player.find_connected_inputs()
            input_player.blocking_playback_of_default_file(
                    input_type='keyboard', filename='keyboard_f4')


    def start_playback(self, blocking_secs=None):
        """Starts Play Video app to play a video file.

        @param blocking_secs: A positive number indicates the timeout to wait
                              for the playback is finished. Set None to make
                              it non-blocking.

        @raises ArcPlayVideoResourceException: Play Video app is not ready or
                                               playback file is not set yet.

        """
        arc.send_keycode(self._KEYCODE_MEDIA_PLAY)

        if blocking_secs:
            tag = lambda : arc.check_android_file_exists(
                    self._PLAYVIDEO_EXIT_TAG)
            exception = error.TestFail('video playback timeout')
            utils.poll_for_condition(tag, exception, blocking_secs)


    def _set_permission(self):
        """Grants permissions to Play Video app."""
        arc.grant_permissions(
                self._PLAYVIDEO_PACKAGE, self._PLAYVIDEO_PERMISSIONS)


    def _start_app(self, dest_path):
        """Starts Play Video app playing a video file.

        @param dest_path: Path to the file to play in container.

        """
        arc.adb_shell('am start --activity-clear-top '
                      '--es PATH {} {}'.format(
                      pipes.quote(dest_path), self._PLAYVIDEO_ACTIVITY))


    def pause_playback(self):
        """Pauses Play Video app.

        Pauses the Play Video app by media key event.

        """
        arc.send_keycode(self._KEYCODE_MEDIA_PAUSE)


    def stop_playback(self):
        """Stops Play Video app.

        Stops the Play Video app by media key event.

        """
        arc.send_keycode(self._KEYCODE_MEDIA_STOP)


    def cleanup(self):
        """Removes the files to play in container."""
        for path in self._files_pushed:
            arc.adb_shell('rm %s' % pipes.quote(path))
        self._files_pushed = []


class ArcResource(object):
    """Class to manage multimedia resource in container.

    @properties:
        microphone: The instance of ArcMicrophoneResource for microphone app.
        play_music: The instance of ArcPlayMusicResource for music app.
        play_video: The instance of ArcPlayVideoResource for video app.

    """
    def __init__(self):
        self.microphone = ArcMicrophoneResource()
        self.play_music = ArcPlayMusicResource()
        self.play_video = ArcPlayVideoResource()


    def cleanup(self):
        """Clean up the resources."""
        self.play_music.cleanup()
        self.play_video.cleanup()
