# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Class for Local sniffers - i.e. running on the local machine.

This class provides configuration for local interfaces but leaves
the actual capture (sniff) to sub-classes.
"""

import os
import shutil
import signal
import subprocess
import tempfile
from mobly import logger
from mobly import utils
from mobly.controllers import sniffer


class SnifferLocalBase(sniffer.Sniffer):
    """This class defines the common behaviors of WLAN sniffers running on
    WLAN interfaces of the local machine.

    Specific mechanisms to capture packets over the local WLAN interfaces are
    implemented by sub-classes of this class - i.e. it is not a final class.
    """

    def __init__(self, interface, logger, base_configs=None):
        """See base class documentation
        """
        self._base_configs = None
        self._capture_file_path = ""
        self._interface = ""
        self._logger = logger
        self._process = None
        self._temp_capture_file_path = ""

        if interface == "":
            raise sniffer.InvalidDataError("Empty interface provided")
        self._interface = interface
        self._base_configs = base_configs

        try:
            subprocess.check_call(['ifconfig', self._interface, 'down'])
            subprocess.check_call(
                ['iwconfig', self._interface, 'mode', 'monitor'])
            subprocess.check_call(['ifconfig', self._interface, 'up'])
        except Exception as err:
            raise sniffer.ExecutionError(err)

    def get_interface(self):
        """See base class documentation
        """
        return self._interface

    def get_type(self):
        """See base class documentation
        """
        return "local"

    def get_capture_file(self):
        return self._capture_file_path

    def _pre_capture_config(self, override_configs=None):
        """Utility function which configures the wireless interface per the
        specified configurations. Operation is performed before every capture
        start using baseline configurations (specified when sniffer initialized)
        and override configurations specified here.
        """
        final_configs = {}
        if self._base_configs:
            final_configs.update(self._base_configs)
        if override_configs:
            final_configs.update(override_configs)

        if sniffer.Sniffer.CONFIG_KEY_CHANNEL in final_configs:
            try:
                subprocess.check_call([
                    'iwconfig', self._interface, 'channel',
                    str(final_configs[sniffer.Sniffer.CONFIG_KEY_CHANNEL])
                ])
            except Exception as err:
                raise sniffer.ExecutionError(err)

    def _get_command_line(self,
                          additional_args=None,
                          duration=None,
                          packet_count=None):
        """Utility function to be implemented by every child class - which
        are the concrete sniffer classes. Each sniffer-specific class should
        derive the command line to execute its sniffer based on the specified
        arguments.
        """
        raise NotImplementedError("Base class should not be called directly!")

    def _post_process(self):
        """Utility function which is executed after a capture is done. It
        moves the capture file to the requested location.
        """
        self._process = None
        shutil.move(self._temp_capture_file_path, self._capture_file_path)

    def start_capture(self,
                      override_configs=None,
                      additional_args=None,
                      duration=None,
                      packet_count=None):
        """See base class documentation
        """
        if self._process is not None:
            raise sniffer.InvalidOperationError(
                "Trying to start a sniff while another is still running!")
        capture_dir = os.path.join(self._logger.log_path,
                                   "Sniffer-{}".format(self._interface))
        os.makedirs(capture_dir, exist_ok=True)
        self._capture_file_path = os.path.join(
            capture_dir,
            "capture_{}.pcap".format(logger.get_log_file_timestamp()))

        self._pre_capture_config(override_configs)
        _, self._temp_capture_file_path = tempfile.mkstemp(suffix=".pcap")

        cmd = self._get_command_line(additional_args=additional_args,
                                     duration=duration,
                                     packet_count=packet_count)

        self._process = utils.start_standing_subprocess(cmd)
        return sniffer.ActiveCaptureContext(self, duration)

    def stop_capture(self):
        """See base class documentation
        """
        if self._process is None:
            raise sniffer.InvalidOperationError(
                "Trying to stop a non-started process")
        utils.stop_standing_subprocess(self._process)
        self._post_process()

    def wait_for_capture(self, timeout=None):
        """See base class documentation
        """
        if self._process is None:
            raise sniffer.InvalidOperationError(
                "Trying to wait on a non-started process")
        try:
            utils.wait_for_standing_subprocess(self._process, timeout)
            self._post_process()
        except subprocess.TimeoutExpired:
            self.stop_capture()
