# Copyright (c) 2012 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.

"""This module provides MTB parser and related packet methods."""

import copy
import logging
import math
import os
import re
import sys

from collections import defaultdict, namedtuple, OrderedDict

from firmware_constants import AXIS, GV, MTB, UNIT, VAL
from geometry.elements import Point
from geometry.two_farthest_clusters import (
        get_radii_of_two_minimal_enclosing_circles as get_two_min_radii,
        get_two_farthest_points
)
sys.path.append('../../bin/input')
from linux_input import *


# Define TidPacket to keep the point, pressure, and SYN_REPOT time of a packet.
TidPacket = namedtuple('TidPacket', ['syn_time', 'point', 'pressure'])


# Define FingerPath class to keep track of the slot, and a list of tid packets
# of a finger (i.e., a tracking ID).
class FingerPath(namedtuple('FingerPath', ['slot', 'tid_packets'])):
    """This keeps the slot number and the list of tid packets of a finger."""
    __slots__ = ()

    def get(self, attr):
        """Get the list of the specified attribute, attr (i.e., point,
        pressure, or syn_time), of TidPacket for the finger.
        """
        return [getattr(tid_packet, attr) for tid_packet in self.tid_packets]


def get_mtb_packets_from_file(event_file):
    """ A helper function to get mtb packets by parsing the event file.

    @param event_file: an mtb_event file
    """
    return Mtb(packets=MtbParser().parse_file(event_file))


def make_pretty_packet(packet):
    """Convert the event list in a packet to a pretty format."""
    pretty_packet = []
    for event in packet:
        pretty_event = []
        pretty_event.append('Event:')
        pretty_event.append('time %.6f,' % event[MTB.EV_TIME])
        if event.get(MTB.SYN_REPORT):
            pretty_event.append('-------------- SYN_REPORT ------------\n')
        else:
            ev_type = event[MTB.EV_TYPE]
            pretty_event.append('type %d (%s),' % (ev_type, EV_TYPES[ev_type]))
            ev_code = event[MTB.EV_CODE]
            pretty_event.append('code %d (%s),' %
                                 (ev_code, EV_STRINGS[ev_type][ev_code]))
            pretty_event.append('value %d' % event[MTB.EV_VALUE])
        pretty_packet.append(' '.join(pretty_event))
    return '\n'.join(pretty_packet)


def convert_to_evemu_format(packets):
    """Convert the text event format to the evemu format."""
    evemu_output = []
    evemu_format = 'E: %.6f %04x %04x %d'
    evemu_format_syn_report = 'E: %.6f 0000 0000 0'
    for packet in packets:
        for event in packet:
            if event.get(MTB.SYN_REPORT):
                evemu_event = evemu_format_syn_report % event[MTB.EV_TIME]
            else:
                evemu_event = evemu_format % (event[MTB.EV_TIME],
                                              event[MTB.EV_TYPE],
                                              event[MTB.EV_CODE],
                                              event[MTB.EV_VALUE])
            evemu_output.append(evemu_event)
    return evemu_output


def convert_mtplot_file_to_evemu_file(mtplot_file, evemu_dir=None,
                                      evemu_ext='.evemu', force=False):
    """Convert a mtplot event file to an evemu event file.

    Example:
       'one_finger_swipe.dat' is converted to 'one_finger_swipe.evemu.dat'
    """
    if not os.path.isfile(mtplot_file):
        print 'Error: there is no such file: "%s".' % mtplot_file
        return None

    # Convert mtplot event format to evemu event format.
    mtplot_packets = MtbParser().parse_file(mtplot_file)
    evemu_packets = convert_to_evemu_format(mtplot_packets)

    # Create the evemu file from the mtplot file.
    mtplot_dir, mtplot_filename = os.path.split(mtplot_file)
    mtplot_basename, mtplot_ext = os.path.splitext(mtplot_filename)

    evemu_dir = evemu_dir if evemu_dir else mtplot_dir
    evemu_file = (os.path.join(evemu_dir, mtplot_basename) + evemu_ext +
                  mtplot_ext)

    # Make sure that the file to be created does not exist yet unless force flag
    # is set to be True.
    if os.path.isfile(evemu_file) and not force:
        print 'Warning: the "%s" already exists. Quit.' % evemu_file
        return None

    # Write the converted evemu events to the evemu file.
    try:
        with open(evemu_file, 'w') as evemu_f:
            evemu_f.write('\n'.join(evemu_packets))
    except Exception as e:
        print 'Error: cannot write data to %s' % evemu_file
        return None

    return evemu_file


class MtbEvent:
    """Determine what an MTB event is.

    This class is just a bundle of a variety of classmethods about
    MTB event classification.
    """
    @classmethod
    def is_ABS_MT_TRACKING_ID(cls, event):
        """Is this event ABS_MT_TRACKING_ID?"""
        return (not event.get(MTB.SYN_REPORT) and
                event[MTB.EV_TYPE] == EV_ABS and
                event[MTB.EV_CODE] == ABS_MT_TRACKING_ID)

    @classmethod
    def is_new_contact(cls, event):
        """Is this packet generating new contact (Tracking ID)?"""
        return cls.is_ABS_MT_TRACKING_ID(event) and event[MTB.EV_VALUE] != -1

    @classmethod
    def is_finger_leaving(cls, event):
        """Is the finger is leaving in this packet?"""
        return cls.is_ABS_MT_TRACKING_ID(event) and event[MTB.EV_VALUE] == -1

    @classmethod
    def is_ABS_MT_SLOT(cls, event):
        """Is this packet ABS_MT_SLOT?"""
        return (not event.get(MTB.SYN_REPORT) and
                event[MTB.EV_TYPE] == EV_ABS and
                event[MTB.EV_CODE] == ABS_MT_SLOT)

    @classmethod
    def is_ABS_MT_POSITION_X(cls, event):
        """Is this packet ABS_MT_POSITION_X?"""
        return (not event.get(MTB.SYN_REPORT) and
                event[MTB.EV_TYPE] == EV_ABS and
                event[MTB.EV_CODE] == ABS_MT_POSITION_X)

    @classmethod
    def is_ABS_MT_POSITION_Y(cls, event):
        """Is this packet ABS_MT_POSITION_Y?"""
        return (not event.get(MTB.SYN_REPORT) and
                event[MTB.EV_TYPE] == EV_ABS and
                event[MTB.EV_CODE] == ABS_MT_POSITION_Y)

    @classmethod
    def is_ABS_MT_PRESSURE(self, event):
        """Is this packet ABS_MT_PRESSURE?"""
        return (not event.get(MTB.SYN_REPORT) and
                event[MTB.EV_TYPE] == EV_ABS and
                event[MTB.EV_CODE] == ABS_MT_PRESSURE)

    @classmethod
    def is_EV_KEY(cls, event):
        """Is this an EV_KEY event?"""
        return (not event.get(MTB.SYN_REPORT) and event[MTB.EV_TYPE] == EV_KEY)

    @classmethod
    def is_BTN_LEFT(cls, event):
        """Is this event BTN_LEFT?"""
        return (cls.is_EV_KEY(event) and event[MTB.EV_CODE] == BTN_LEFT)

    @classmethod
    def is_BTN_LEFT_value(cls, event, value):
        """Is this event BTN_LEFT with value equal to the specified value?"""
        return (cls.is_BTN_LEFT(event) and event[MTB.EV_VALUE] == value)

    @classmethod
    def is_BTN_TOOL_FINGER(cls, event):
        """Is this event BTN_TOOL_FINGER?"""
        return (cls.is_EV_KEY(event) and
                event[MTB.EV_CODE] == BTN_TOOL_FINGER)

    @classmethod
    def is_BTN_TOOL_DOUBLETAP(cls, event):
        """Is this event BTN_TOOL_DOUBLETAP?"""
        return (cls.is_EV_KEY(event) and
                event[MTB.EV_CODE] == BTN_TOOL_DOUBLETAP)

    @classmethod
    def is_BTN_TOOL_TRIPLETAP(cls, event):
        """Is this event BTN_TOOL_TRIPLETAP?"""
        return (cls.is_EV_KEY(event) and
                event[MTB.EV_CODE] == BTN_TOOL_TRIPLETAP)

    @classmethod
    def is_BTN_TOOL_QUADTAP(cls, event):
        """Is this event BTN_TOOL_QUADTAP?"""
        return (cls.is_EV_KEY(event) and
                event[MTB.EV_CODE] == BTN_TOOL_QUADTAP)

    @classmethod
    def is_BTN_TOOL_QUINTTAP(cls, event):
        """Is this event BTN_TOOL_QUINTTAP?"""
        return (cls.is_EV_KEY(event) and
                event[MTB.EV_CODE] == BTN_TOOL_QUINTTAP)

    @classmethod
    def is_BTN_TOUCH(cls, event):
        """Is this event BTN_TOUCH?"""
        return (cls.is_EV_KEY(event) and
                event[MTB.EV_CODE] == BTN_TOUCH)

    @classmethod
    def is_SYN_REPORT(self, event):
        """Determine if this event is SYN_REPORT."""
        return event.get(MTB.SYN_REPORT, False)


class MtbEvemu:
    """A simplified class provides MTB utilities for evemu event format."""
    def __init__(self, device):
        self.mtb = Mtb(device=device)
        self.num_tracking_ids = 0

    def _convert_event(self, event):
        (tv_sec, tv_usec, ev_type, ev_code, ev_value) = event
        ev_dict = {MTB.EV_TIME: tv_sec + 0.000001 * tv_usec,
                   MTB.EV_TYPE: ev_type,
                   MTB.EV_CODE: ev_code,
                   MTB.EV_VALUE: ev_value}
        return ev_dict

    def all_fingers_leaving(self):
        """Is there no finger on the touch device?"""
        return self.num_tracking_ids <= 0

    def process_event(self, event):
        """Process the event and count existing fingers."""
        converted_event = self._convert_event(event)
        if MtbEvent.is_new_contact(converted_event):
            self.num_tracking_ids += 1
        elif MtbEvent.is_finger_leaving(converted_event):
            self.num_tracking_ids -= 1


class MtbStateMachine:
    """The state machine for MTB events.

    It traces the slots, tracking IDs, x coordinates, y coordinates, etc. If
    these values are not changed explicitly, the values are kept across events.

    Note that the kernel driver only reports what is changed. Due to its
    internal state machine, it is possible that either x or y in
    self.point[tid] is None initially even the instance has been created.
    """
    def __init__(self):
        # Set the default slot to 0 as it may not be displayed in the MTB events
        #
        # Some abnormal event files may not display the tracking ID in the
        # beginning. To handle this situation, we need to initialize
        # the following variables:  slot_to_tid, point
        #
        # As an example, refer to the following event file which is one of
        # the golden samples with this problem.
        #   tests/data/stationary_finger_shift_with_2nd_finger_tap.dat
        self.tid = None
        self.slot = 0
        self.slot_to_tid = {self.slot: self.tid}
        self.point = {self.tid: Point()}
        self.pressure = {self.tid: None}
        self.syn_time = None
        self.new_tid = False
        self.number_fingers = 0
        self.leaving_slots = []

    def _del_leaving_slots(self):
        """Delete the leaving slots. Remove the slots and their tracking IDs."""
        for slot in self.leaving_slots:
            del self.slot_to_tid[slot]
            self.number_fingers -= 1
        self.leaving_slots = []

    def add_event(self, event):
        """Update the internal states with the event.

        @param event: an MTB event
        """
        self.new_tid = False

        # Switch the slot.
        if MtbEvent.is_ABS_MT_SLOT(event):
            self.slot = event[MTB.EV_VALUE]

        # Get a new tracking ID.
        elif MtbEvent.is_new_contact(event):
            self.tid = event[MTB.EV_VALUE]
            self.slot_to_tid[self.slot] = self.tid
            self.new_tid = True
            self.point[self.tid] = Point()
            self.number_fingers += 1

        # A slot is leaving.
        # Do not delete this slot until this last packet is reported.
        elif MtbEvent.is_finger_leaving(event):
            self.leaving_slots.append(self.slot)

        # Update x value.
        elif MtbEvent.is_ABS_MT_POSITION_X(event):
            self.point[self.slot_to_tid[self.slot]].x = event[MTB.EV_VALUE]

        # Update y value.
        elif MtbEvent.is_ABS_MT_POSITION_Y(event):
            self.point[self.slot_to_tid[self.slot]].y = event[MTB.EV_VALUE]

        # Update z value (pressure)
        elif MtbEvent.is_ABS_MT_PRESSURE(event):
            self.pressure[self.slot_to_tid[self.slot]] = event[MTB.EV_VALUE]

        # Use the SYN_REPORT time as the packet time
        elif MtbEvent.is_SYN_REPORT(event):
            self.syn_time = event[MTB.EV_TIME]

    def get_current_tid_data_for_all_tids(self, request_data_ready=True):
        """Get current packet's tid data including the point, the pressure, and
        the syn_time for all tids.

        @param request_data_ready: if set to true, it will not output
                current_tid_data until all data including x, y, pressure,
                syn_time, etc. in the packet have been assigned.
        """
        current_tid_data = []
        for slot, tid in self.slot_to_tid.items():
            point = copy.deepcopy(self.point.get(tid))
            pressure = self.pressure.get(tid)
            # Check if all attributes are non-None values.
            # Note: we cannot use
            #           all([all(point.value()), pressure, self.syn_time])
            #       E.g., for a point = (0, 300), it will return False
            #       which is not what we want. We want it to return False
            #       only when there are None values.
            data_ready = all(map(lambda e: e is not None,
                             list(point.value()) + [pressure, self.syn_time]))

            if (not request_data_ready) or data_ready:
                tid_packet = TidPacket(self.syn_time, point, pressure)
            else:
                tid_packet = None
            # Even tid_packet is None, we would like to report this tid so that
            # its client function get_ordered_finger_paths() could construct
            # an ordered dictionary correctly based on the tracking ID.
            current_tid_data.append((tid, slot, tid_packet))

        self._del_leaving_slots()

        return sorted(current_tid_data)


class Mtb:
    """An MTB class providing MTB format related utility methods."""
    LEN_MOVING_AVERAGE = 2
    LEVEL_JUMP_RATIO = 3
    LEVEL_JUMP_MAXIUM_ALLOWED = 10
    LEN_DISCARD = 5

    def __init__(self, device=None, packets=None):
        self.device = device
        self.packets = packets
        self._define_check_event_func_list()

    def _define_check_event_func_list(self):
        """Define event function lists for various event cycles below."""
        self.check_event_func_list = {}
        self.MAX_FINGERS = 5
        # One-finger touching the device should generate the following events:
        #     BTN_TOUCH, and BTN_TOOL_FINGER: 0 -> 1 -> 0
        self.check_event_func_list[1] = [MtbEvent.is_BTN_TOUCH,
                                         MtbEvent.is_BTN_TOOL_FINGER]

        # Two-finger touching the device should generate the following events:
        #     BTN_TOUCH, and BTN_TOOL_DOUBLETAP: 0 -> 1 -> 0
        self.check_event_func_list[2] = [MtbEvent.is_BTN_TOUCH,
                                         MtbEvent.is_BTN_TOOL_DOUBLETAP]

        # Three-finger touching the device should generate the following events:
        #     BTN_TOUCH, and BTN_TOOL_TRIPLETAP: 0 -> 1 -> 0
        self.check_event_func_list[3] = [MtbEvent.is_BTN_TOUCH,
                                         MtbEvent.is_BTN_TOOL_TRIPLETAP]

        # Four-finger touching the device should generate the following events:
        #     BTN_TOUCH, and BTN_TOOL_QUADTAP: 0 -> 1 -> 0
        self.check_event_func_list[4] = [MtbEvent.is_BTN_TOUCH,
                                         MtbEvent.is_BTN_TOOL_QUADTAP]

        # Five-finger touching the device should generate the following events:
        #     BTN_TOUCH, and BTN_TOOL_QUINTTAP: 0 -> 1 -> 0
        self.check_event_func_list[5] = [MtbEvent.is_BTN_TOUCH,
                                         MtbEvent.is_BTN_TOOL_QUINTTAP]

        # Physical click should generate the following events:
        #     BTN_LEFT: 0 -> 1 -> 0
        self.check_event_func_click = [MtbEvent.is_BTN_LEFT,]



    def _calc_movement_for_axis(self, x, prev_x):
        """Calculate the distance moved in an axis."""
        return abs(x - prev_x) if prev_x is not None else 0

    def _calc_distance(self, (x0, y0), (x1, y1)):
        """Calculate the distance in pixels between two points."""
        dist_x = x1 - x0
        dist_y = y1 - y0
        return math.sqrt(dist_x * dist_x + dist_y * dist_y)

    def _init_dict(self, keys, value):
        """Initialize a dictionary over the keys with the same given value.

        Note: The following command does not always work:
                    dict.fromkeys(keys, value)
              It works when value is a simple type, e.g., an integer.
              However, if value is [] or {}, it does not work correctly.
              The reason is that if the value is [] or {}, all the keys would
              point to the same list or dictionary, which is not expected
              in most cases.
        """
        return dict([(key, copy.deepcopy(value)) for key in keys])

    def get_number_contacts(self):
        """Get the number of contacts (Tracking IDs)."""
        num_contacts = 0
        for packet in self.packets:
            for event in packet:
                if MtbEvent.is_new_contact(event):
                    num_contacts += 1
        return num_contacts

    def get_x_y(self, target_slot):
        """Extract x and y positions in the target slot."""
        # The default slot is slot 0 if no slot number is assigned.
        # The rationale is that evdev is a state machine. It only reports
        # the change. Slot 0 would not be reported by evdev if last time
        # the last finger left the touch device was at slot 0.
        slot = 0

        # Should not write "list_x = list_y = []" below.
        # They would end up with pointing to the same list.
        list_x = []
        list_y = []
        prev_x = prev_y = None
        target_slot_live = False
        initial_default_slot_0 = True
        for packet in self.packets:
            if (slot == target_slot and slot == 0 and not target_slot_live and
                initial_default_slot_0):
                target_slot_live = True
                initial_default_slot_0 = False
            for event in packet:
                if MtbEvent.is_ABS_MT_SLOT(event):
                    slot = event[MTB.EV_VALUE]
                    if slot == target_slot and not target_slot_live:
                        target_slot_live = True
                if slot != target_slot:
                    continue

                # Update x value if available.
                if MtbEvent.is_ABS_MT_POSITION_X(event):
                    prev_x = event[MTB.EV_VALUE]
                # Update y value if available.
                elif MtbEvent.is_ABS_MT_POSITION_Y(event):
                    prev_y = event[MTB.EV_VALUE]
                # Check if the finger at the target_slot is leaving.
                elif MtbEvent.is_finger_leaving(event):
                    target_slot_live = False

            # If target_slot is alive, and both x and y have
            # been assigned values, append the x and y to the list no matter
            # whether x or y position is reported in the current packet.
            # This also handles the initial condition that no previous x or y
            # is reported yet.
            if target_slot_live and prev_x and prev_y:
                list_x.append(prev_x)
                list_y.append(prev_y)
        return (list_x, list_y)

    def get_ordered_finger_paths(self, request_data_ready=True):
        """Construct the finger paths ordered by the occurrences of the
        finger contacts.

        @param request_data_ready: if set to true, it will not output the
                tid_data in a packet until all data including x, y, pressure,
                syn_time, etc. in the packet have been assigned.

        The finger_paths mapping the tid to its finger_path looks like
            {tid1: finger_path1,
             tid2: finger_path2,
             ...
            }
        where every tid represents a finger.

        A finger_path effectively consists of a list of tid_packets of the same
        tid in the event file. An example of its structure looks like
        finger_path:
            slot=0
            tid_packets = [tid_packet0, tid_packet1, tid_packet2, ...]

        A tid_packet looks like
            [100021.342104,         # syn_time
             (66, 100),             # point
             56,                    # pressure
             ...                    # maybe more attributes added later.
            ]

        This method is applicable when fingers are contacting and leaving
        the touch device continuously. The same slot number, e.g., slot 0 or
        slot 1, may be used for multiple times.

        Note that the finger contact starts at 0. The finger contacts look to
        be equal to the slot numbers in practice. However, this assumption
        seems not enforced in any document. For safety, we use the ordered
        finger paths dict here to guarantee that we could access the ith finger
        contact path data correctly.

        Also note that we do not sort finger paths by tracking IDs to derive
        the ordered dict because tracking IDs may wrap around.
        """
        # ordered_finger_paths_dict is an ordered dictionary of
        #     {tid: FingerPath}
        ordered_finger_paths_dict = OrderedDict()
        sm = MtbStateMachine()
        for packet in self.packets:
            # Inject events into the state machine to update its state.
            for event in packet:
                sm.add_event(event)

            # If there are N fingers (tids) in a packet, we will have
            # N tid_packet's in the current packet. The loop below is to
            # append every tid_packet into its corresponding finger_path for
            # every tracking id in the current packet.
            for tid, slot, tid_packet in sm.get_current_tid_data_for_all_tids(
                    request_data_ready):
                finger_path = ordered_finger_paths_dict.setdefault(
                        tid, FingerPath(slot, []))
                if tid_packet:
                    finger_path.tid_packets.append(tid_packet)

        return ordered_finger_paths_dict

    def get_ordered_finger_path(self, finger, attr):
        """Extract the specified attribute from the packets of the ith finger
        contact.

        @param finger: the ith finger contact
        @param attr: an attribute in a tid packet which could be either
                'point', 'pressure', or 'syn_time'
        """
        # finger_paths is a list ordered by the occurrences of finger contacts
        finger_paths = self.get_ordered_finger_paths().values()
        if finger < len(finger_paths) and finger >= 0:
            finger_path = finger_paths[finger]
            return finger_path.get(attr)
        return []

    def get_slot_data(self, slot, attr):
        """Extract the attribute data of the specified slot.

        @param attr: an attribute in a tid packet which could be either
                'point', 'pressure', or 'syn_time'
        """
        for finger_path in self.get_ordered_finger_paths().values():
            if finger_path.slot == slot:
                return finger_path.get(attr)
        return []

    def get_max_distance_of_all_tracking_ids(self):
        """Get the max moving distance of all tracking IDs."""
        return max(max(get_two_min_radii(finger_path.get('point'))
            for finger_path in self.get_ordered_finger_paths().values()))

    def get_list_of_rocs_of_all_tracking_ids(self):
        """For each tracking ID, compute the minimal enclosing circles.

        Return a list of radii of such minimal enclosing circles of
        all tracking IDs.
        Note: rocs denotes the radii of circles
        """
        list_rocs = []
        for finger_path in self.get_ordered_finger_paths().values():
            # Convert the point coordinates in pixels to in mms.
            points_in_mm = [Point(*self.device.pixel_to_mm(p.value()))
                            for p in finger_path.get('point')]
            list_rocs += get_two_min_radii(points_in_mm)
        return list_rocs

    def get_x_y_multiple_slots(self, target_slots):
        """Extract points in multiple slots.

        Only the packets with all specified slots are extracted.
        This is useful to collect packets for pinch to zoom.
        """
        # Initialize slot_exists dictionary to False
        slot_exists = dict.fromkeys(target_slots, False)

        # Set the initial slot number to 0 because evdev is a state machine,
        # and may not present slot 0.
        slot = 0
        # Initialize the following dict to []
        # Don't use "dict.fromkeys(target_slots, [])"
        list_x = self._init_dict(target_slots, [])
        list_y = self._init_dict(target_slots, [])
        x = self._init_dict(target_slots, None)
        y = self._init_dict(target_slots, None)
        for packet in self.packets:
            for event in packet:
                if MtbEvent.is_ABS_MT_SLOT(event):
                    slot = event[MTB.EV_VALUE]
                if slot not in target_slots:
                    continue

                if MtbEvent.is_ABS_MT_TRACKING_ID(event):
                    if MtbEvent.is_new_contact(event):
                        slot_exists[slot] = True
                    elif MtbEvent.is_finger_leaving(event):
                        slot_exists[slot] = False
                elif MtbEvent.is_ABS_MT_POSITION_X(event):
                    x[slot] = event[MTB.EV_VALUE]
                elif MtbEvent.is_ABS_MT_POSITION_Y(event):
                    y[slot] = event[MTB.EV_VALUE]

            # Note:
            # - All slot_exists must be True to append x, y positions for the
            #   slots.
            # - All x and y values for all slots must have been reported once.
            #   (This handles the initial condition that no previous x or y
            #    is reported yet.)
            # - If either x or y positions are reported in the current packet,
            #   append x and y to the list of that slot.
            #   (This handles the condition that only x or y is reported.)
            # - Even in the case that neither x nor y is reported in current
            #   packet, cmt driver constructs and passes hwstate to gestures.
            if (all(slot_exists.values()) and all(x.values()) and
                all(y.values())):
                for s in target_slots:
                    list_x[s].append(x[s])
                    list_y[s].append(y[s])

        return (list_x, list_y)

    def get_points_multiple_slots(self, target_slots):
        """Get the points in multiple slots."""
        list_x, list_y = self.get_x_y_multiple_slots(target_slots)
        points_list = [zip(list_x[slot], list_y[slot]) for slot in target_slots]
        points_dict = dict(zip(target_slots, points_list))
        return points_dict

    def get_relative_motion(self, target_slots):
        """Get the relative motion of the two target slots."""
        # The slots in target_slots could be (0, 1), (1, 2) or other
        # possibilities.
        slot_a, slot_b = target_slots
        points_dict = self.get_points_multiple_slots(target_slots)
        points_slot_a = points_dict[slot_a]
        points_slot_b = points_dict[slot_b]

        # if only 0 or 1 point observed, the relative motion is 0.
        if len(points_slot_a) <= 1 or len(points_slot_b) <= 1:
            return 0

        distance_begin = self._calc_distance(points_slot_a[0], points_slot_b[0])
        distance_end = self._calc_distance(points_slot_a[-1], points_slot_b[-1])
        relative_motion = distance_end - distance_begin
        return relative_motion

    def get_points(self, target_slot):
        """Get the points in the target slot."""
        list_x, list_y = self.get_x_y(target_slot)
        return zip(list_x, list_y)

    def get_distances(self, target_slot):
        """Get the distances of neighbor points in the target slot."""
        points = self.get_points(target_slot)
        distances = []
        for index in range(len(points) - 1):
            distance = self._calc_distance(points[index], points[index + 1])
            distances.append(distance)
        return distances

    def get_range(self):
        """Get the min and max values of (x, y) positions."""
        min_x = min_y = float('infinity')
        max_x = max_y = float('-infinity')
        for packet in self.packets:
            for event in packet:
                if MtbEvent.is_ABS_MT_POSITION_X(event):
                    x = event[MTB.EV_VALUE]
                    min_x = min(min_x, x)
                    max_x = max(max_x, x)
                elif MtbEvent.is_ABS_MT_POSITION_Y(event):
                    y = event[MTB.EV_VALUE]
                    min_y = min(min_y, y)
                    max_y = max(max_y, y)
        return (min_x, max_x, min_y, max_y)

    def get_total_motion(self, target_slot):
        """Get the total motion in the target slot."""
        prev_x = prev_y = None
        accu_x = accu_y = 0
        slot = None
        for packet in self.packets:
            for event in packet:
                if MtbEvent.is_ABS_MT_SLOT(event):
                    slot = event[MTB.EV_VALUE]
                elif (MtbEvent.is_ABS_MT_POSITION_X(event) and
                      slot == target_slot):
                    x = event[MTB.EV_VALUE]
                    accu_x += self._calc_movement_for_axis(x, prev_x)
                    prev_x = x
                elif (MtbEvent.is_ABS_MT_POSITION_Y(event) and
                      slot == target_slot):
                    y = event[MTB.EV_VALUE]
                    accu_y += self._calc_movement_for_axis(y, prev_y)
                    prev_y = y
        return (accu_x, accu_y)

    def get_max_distance(self, slot, unit):
        """Get the max distance between any two points of the specified slot."""
        points = self.get_slot_data(slot, 'point')
        return self.get_max_distance_from_points(points, unit)

    def get_max_distance_from_points(self, points, unit):
        """Get the max distance between any two points."""
        two_farthest_points = get_two_farthest_points(points)
        if len(two_farthest_points) < 2:
            return 0

        # Convert the point coordinates from pixel to mm if necessary.
        if unit == UNIT.MM:
            p1, p2 = [Point(*self.device.pixel_to_mm(p.value()))
                      for p in two_farthest_points]
        else:
            p1, p2 = two_farthest_points

        return p1.distance(p2)

    def get_largest_gap_ratio(self, target_slot):
        """Get the largest gap ratio in the target slot.

        gap_ratio_with_prev = curr_gap / prev_gap
        gap_ratio_with_next = curr_gap / next_gap

        This function tries to find the largest gap_ratio_with_prev
        with the restriction that gap_ratio_with_next is larger than
        RATIO_THRESHOLD_CURR_GAP_TO_NEXT_GAP.

        The ratio threshold is used to prevent the gaps detected in a swipe.
        Note that in a swipe, the gaps tends to become larger and larger.
        """
        RATIO_THRESHOLD_CURR_GAP_TO_NEXT_GAP = 1.2
        GAP_LOWER_BOUND = 10

        gaps = self.get_distances(target_slot)
        gap_ratios = []
        largest_gap_ratio = float('-infinity')
        for index in range(1, len(gaps) - 1):
            prev_gap = max(gaps[index - 1], 1)
            curr_gap = gaps[index]
            next_gap = max(gaps[index + 1], 1)
            gap_ratio_with_prev = curr_gap / prev_gap
            gap_ratio_with_next = curr_gap / next_gap
            if (curr_gap >= GAP_LOWER_BOUND and
                gap_ratio_with_prev > largest_gap_ratio and
                gap_ratio_with_next > RATIO_THRESHOLD_CURR_GAP_TO_NEXT_GAP):
                largest_gap_ratio = gap_ratio_with_prev

        return largest_gap_ratio

    def _is_large(self, numbers, index):
        """Is the number at the index a large number compared to the moving
        average of the previous LEN_MOVING_AVERAGE numbers? This is used to
        determine if a distance is a level jump."""
        if index < self.LEN_MOVING_AVERAGE + 1:
            return False
        moving_sum = sum(numbers[index - self.LEN_MOVING_AVERAGE : index])
        moving_average = float(moving_sum) / self.LEN_MOVING_AVERAGE
        cond1 = numbers[index] >= self.LEVEL_JUMP_RATIO * moving_average
        cond2 = numbers[index] >= self.LEVEL_JUMP_MAXIUM_ALLOWED
        return cond1 and cond2

    def _accumulate_level_jumps(self, level_jumps):
        """Accumulate level jumps."""
        if not level_jumps:
            return []

        is_positive = level_jumps[0] > 0
        tmp_sum = 0
        accumulated_level_jumps = []
        for jump in level_jumps:
            # If current sign is the same as previous ones, accumulate it.
            if (jump > 0) is is_positive:
                tmp_sum += jump
            # If current jump has changed its sign, reset the tmp_sum to
            # accumulate the level_jumps onwards.
            else:
                accumulated_level_jumps.append(tmp_sum)
                tmp_sum = jump
                is_positive = not is_positive

        if tmp_sum != 0:
            accumulated_level_jumps.append(tmp_sum)
        return accumulated_level_jumps

    def get_largest_accumulated_level_jumps(self, displacements):
        """Get the largest accumulated level jumps in displacements."""
        largest_accumulated_level_jumps = 0
        if len(displacements) < self.LEN_MOVING_AVERAGE + 1:
            return largest_accumulated_level_jumps

        # Truncate some elements at both ends of the list which are not stable.
        displacements = displacements[self.LEN_DISCARD: -self.LEN_DISCARD]
        distances = map(abs, displacements)

        # E.g., displacements= [5, 6, 5, 6, 20, 3, 5, 4, 6, 21, 4, ...]
        #       level_jumps = [20, 21, ...]
        level_jumps = [disp for i, disp in enumerate(displacements)
                       if self._is_large(distances, i)]

        # E.g., level_jumps= [20, 21, -18, -25, 22, 18, -19]
        #       accumulated_level_jumps = [41, -43, 40, -19]
        #       largest_accumulated_level_jumps = 43
        accumulated_level_jumps = self._accumulate_level_jumps(level_jumps)
        if accumulated_level_jumps:
            abs_accumulated_level_jumps = map(abs, accumulated_level_jumps)
            largest_accumulated_level_jumps = max(abs_accumulated_level_jumps)

        return largest_accumulated_level_jumps

    def get_displacement(self, target_slot):
        """Get the displacement in the target slot."""
        displace = [map(lambda p0, p1: p1 - p0, axis[:len(axis) - 1], axis[1:])
                    for axis in self.get_x_y(target_slot)]
        displacement_dict = dict(zip((AXIS.X, AXIS.Y), displace))
        return displacement_dict

    def calc_displacement(self, numbers):
        """Calculate the displacements in a list of numbers."""
        if len(numbers) <= 1:
            return []
        return [numbers[i + 1] - numbers[i] for i in range(len(numbers) - 1)]

    def get_displacements_for_slots(self, min_slot):
        """Get the displacements for slots >= min_slot."""
        finger_paths = self.get_ordered_finger_paths()

        # Remove those tracking IDs with slots < min_slot
        for tid, finger_path in finger_paths.items():
            if finger_path.slot < min_slot:
                del finger_paths[tid]

        # Calculate the displacements of the coordinates in the tracking IDs.
        displacements = defaultdict(dict)
        for tid, finger_path in finger_paths.items():
            finger_path_values = [p.value() for p in finger_path.get('point')]
            if finger_path_values:
                list_x, list_y = zip(*finger_path_values)
            else:
                list_x, list_y = [], []
            displacements[tid][MTB.SLOT] = finger_path.slot
            displacements[tid][AXIS.X] = self.calc_displacement(list_x)
            displacements[tid][AXIS.Y] = self.calc_displacement(list_y)

        return displacements

    def _get_segments_by_length(self, src_list, segment_flag, ratio):
        """Get the segments based on segment_flag and the ratio of the
        src_list length (size).

        @param src_list: could be list_x, list_y, or list_t
        @param segment_flag: indicating which segment (the begin, the end, or
                the middle segment) to extract
        @param ratio: the ratio of the time interval of the segment
        """
        end_size = int(round(len(src_list) * ratio))
        if segment_flag == VAL.WHOLE:
            return src_list
        elif segment_flag == VAL.MIDDLE:
            return src_list[end_size: -end_size]
        elif segment_flag == VAL.BEGIN:
            return src_list[: end_size]
        elif segment_flag == VAL.END:
            return src_list[-end_size:]
        elif segment_flag == VAL.BOTH_ENDS:
            bgn_segment = src_list[: end_size]
            end_segment = src_list[-end_size:]
            return bgn_segment + end_segment
        else:
            return None

    def get_segments_x_and_y(self, ax, ay, segment_flag, ratio):
        """Get the segments for both x and y axes."""
        segment_x = self._get_segments_by_length(ax, segment_flag, ratio)
        segment_y = self._get_segments_by_length(ay, segment_flag, ratio)
        return (segment_x, segment_y)

    def get_segments_by_distance(self, list_t, list_coord, segment_flag, ratio):
        """Partition list_coord into the begin, the middle, and the end
        segments based on segment_flag and the ratio. And then use the
        derived indexes to partition list_t.

        @param list_t: the list of syn_report time instants
        @param list_coord: could be list_x, list_y
        @param segment_flag: indicating which segment (the being, the end, or
                the middle segment) to extract
        @param ratio: the ratio of the distance of the begin/end segment
                with the value between 0.0 and 1.0
        """
        def _find_boundary_index(list_coord, boundary_distance):
            """Find the boundary index i such that
               abs(list_coord[i] - list_coord[0]) > boundary_distance

            @param list_coord: a list of coordinates
            @param boundary_distance: the min distance between boundary_coord
                    and list_coord[0]
            """
            for i, c in enumerate(list_coord):
                if abs(c - list_coord[0]) > boundary_distance:
                    return i

        end_to_end_distance = abs(list_coord[-1] - list_coord[0])
        first_idx_mid_seg = _find_boundary_index(
                list_coord, end_to_end_distance * ratio)
        last_idx_mid_seg = _find_boundary_index(
                list_coord, end_to_end_distance * (1 - ratio))

        if segment_flag == VAL.WHOLE:
            segment_coord = list_coord
            segment_t = list_t
        elif segment_flag == VAL.MIDDLE:
            segment_coord = list_coord[first_idx_mid_seg:last_idx_mid_seg]
            segment_t = list_t[first_idx_mid_seg:last_idx_mid_seg]
        elif segment_flag == VAL.BEGIN:
            segment_coord = list_coord[:first_idx_mid_seg]
            segment_t = list_t[:first_idx_mid_seg]
        elif segment_flag == VAL.END:
            segment_coord = list_coord[last_idx_mid_seg:]
            segment_t = list_t[last_idx_mid_seg:]
        else:
            segment_coord = []
            segment_t = []

        return (segment_t, segment_coord)

    def get_segments(self, list_t, list_coord, segment_flag, ratio):
        """Partition list_t and list_coord into the segments specified by
        the segment_flag and the ratio.

        If the list_coord stretches long enough, it represents a normal
        line. We will partition list_t and list_coord by distance.

        On the other hand, if the min and max values in list_coord are
        close to each other, it probably does not represent a line. We will
        partition list_t and list_coord by time in this case.
        E.g., in the follow cases, it is better to partition using length
              instead of using distance.
        list_coord = [105, 105, 105, 105, 105, 105, 105, 105, 105, 105] or
        list_coord = [104, 105, 105, 105, 105, 105, 105, 105, 105, 105] or
        list_coord = [105, 105, 105, 105, 105, 105, 105, 105, 105, 106]

        @param list_t: the list of syn_report time instants
        @param list_coord: could be list_x, list_y
        @param segment_flag: indicating which segment (the being, the end, or
                the middle segment) to extract
        @param ratio: the ratio of the distance of the begin/end segment
                with the value between 0.0 and 1.0
        """
        MIN_STRAIGHT_LINE_DIST = 20
        if (max(list_coord) - min(list_coord)) > MIN_STRAIGHT_LINE_DIST:
            return self.get_segments_by_distance(list_t, list_coord,
                                                 segment_flag, ratio)
        else:
            return (self._get_segments_by_length(list_t, segment_flag, ratio),
                    self._get_segments_by_length(list_coord, segment_flag,
                                                 ratio))

    def get_reversed_motions(self, target_slot, direction,
                             segment_flag=VAL.WHOLE, ratio=None):
        """Get the total reversed motions in the specified direction
           in the target slot.

        Only the reversed motions specified by the segment_flag are taken.
        The segment_flag could be
          VAL.BEGIN: the begin segment
          VAL.MIDDLE : the middle segment
          VAL.END : the end segment
          VAL.BOTH_ENDS : the segments at both ends
          VAL.WHOLE: the whole line

        The ratio represents the ratio of the BEGIN or END segment to the whole
        segment.

        If direction is in HORIZONTAL_DIRECTIONS, consider only x axis.
        If direction is in VERTICAL_DIRECTIONS, consider only y axis.
        If direction is in DIAGONAL_DIRECTIONS, consider both x and y axes.

        Assume that the displacements in GV.LR (moving from left to right)
        in the X axis are:

            [10, 12, 8, -9, -2, 6, 8, 11, 12, 5, 2]

        Its total reversed motion = (-9) + (-2) = -11
        """
        # Define the axis moving directions dictionary
        POSITIVE = 'positive'
        NEGATIVE = 'negative'
        AXIS_MOVING_DIRECTIONS = {
            GV.LR: {AXIS.X: POSITIVE},
            GV.RL: {AXIS.X: NEGATIVE},
            GV.TB: {AXIS.Y: POSITIVE},
            GV.BT: {AXIS.Y: NEGATIVE},
            GV.CR: {AXIS.X: POSITIVE},
            GV.CL: {AXIS.X: NEGATIVE},
            GV.CB: {AXIS.Y: POSITIVE},
            GV.CT: {AXIS.Y: NEGATIVE},
            GV.BLTR: {AXIS.X: POSITIVE, AXIS.Y: NEGATIVE},
            GV.BRTL: {AXIS.X: NEGATIVE, AXIS.Y: NEGATIVE},
            GV.TRBL: {AXIS.X: NEGATIVE, AXIS.Y: POSITIVE},
            GV.TLBR: {AXIS.X: POSITIVE, AXIS.Y: POSITIVE},
        }

        axis_moving_directions = AXIS_MOVING_DIRECTIONS.get(direction)
        func_positive = lambda n: n > 0
        func_negative = lambda n: n < 0
        reversed_functions = {POSITIVE: func_negative, NEGATIVE: func_positive}
        displacement_dict = self.get_displacement(target_slot)
        reversed_motions = {}
        for axis in AXIS.LIST:
            axis_moving_direction = axis_moving_directions.get(axis)
            if axis_moving_direction is None:
                continue
            displacement = displacement_dict[axis]
            displacement_segment = self._get_segments_by_length(
                    displacement, segment_flag, ratio)
            reversed_func = reversed_functions[axis_moving_direction]
            reversed_motions[axis] = sum(filter(reversed_func,
                                                displacement_segment))
        return reversed_motions

    def get_num_packets(self, target_slot):
        """Get the number of packets in the target slot."""
        list_x, list_y = self.get_x_y(target_slot)
        return len(list_x)

    def get_list_syn_time(self, finger):
        """Get the list of syn_time instants from the packets of the ith finger
        contact if finger is not None. Otherwise, use all packets.

        @param finger : the specified ith finger contact.
                If a finger contact is specified, extract only the list of
                syn_time from this finger contact.
                Otherwise, when the finger contact is set to None, take all
                packets into account. Note that the finger contact number
                starts from 0.

        Note: the last event in a packet, represented as packet[-1], is
              'SYN_REPORT' of which the event time is the 'syn_time'.
        """
        return (self.get_ordered_finger_path(finger, 'syn_time')
                if isinstance(finger, int) else
                [packet[-1].get(MTB.EV_TIME) for packet in self.packets])

    def _call_check_event_func(self, event, expected_value, check_event_result,
                               check_event_func):
        """Call all functions in check_event_func and return the results.

        Note that since check_event_result is a dictionary, it is passed
        by reference.
        """
        for func in check_event_func:
            if func(event):
                event_value = event[MTB.EV_VALUE]
                check_event_result[func] = (event_value == expected_value)
                break

    def _get_event_cycles(self, check_event_func):
        """A generic method to get the number of event cycles.

        For a tap, its event cycle looks like:
            (1) finger touching the touch device:
                BTN_TOOL_FINGER: 0-> 1
                BTN_TOUCH: 0 -> 1
            (2) finger leaving the touch device:
                BTN_TOOL_FINGER: 1-> 0
                BTN_TOUCH: 1 -> 0

        For a one-finger physical click, its event cycle looks like:
            (1) finger clicking and pressing:
                BTN_LEFT : 0-> 1
                BTN_TOOL_FINGER: 0-> 1
                BTN_TOUCH: 0 -> 1
            (2) finger leaving:
                BTN_LEFT : 1-> 0
                BTN_TOOL_FINGER: 1-> 0
                BTN_TOUCH: 1 -> 0

        This method counts how many such cycles there are in the packets.
        """
        # Initialize all check_event_result to False
        # when all_events_observed is False and all check_event_result are True
        #      => all_events_observed is set to True
        # when all_events_observed is True and all check_event_result are True
        #      => all_events_observed is set to False, and
        #         count is increased by 1
        check_event_result = self._init_dict(check_event_func, False)
        all_events_observed = False
        count = 0
        for packet in self.packets:
            for event in packet:
                if all_events_observed:
                    expected_value = 0
                    self._call_check_event_func(event, expected_value,
                                                check_event_result,
                                                check_event_func)
                    if all(check_event_result.values()):
                        all_events_observed = False
                        check_event_result = self._init_dict(check_event_func,
                                                             False)
                        count += 1
                else:
                    expected_value = 1
                    self._call_check_event_func(event, expected_value,
                                                check_event_result,
                                                check_event_func)
                    if all(check_event_result.values()):
                        all_events_observed = True
                        check_event_result = self._init_dict(check_event_func,
                                                             False)
        return count

    def _get_event_cycles_for_num_fingers(self, num_fingers):
        return self._get_event_cycles(self.check_event_func_list[num_fingers])

    def verify_exact_number_fingers_touch(self, num_fingers):
        """Verify the exact number of fingers touching the device.

        Example: for a two-finger touch
            2-finger touch cycles should be equal to 1
            3/4/5-finger touch cycles should be equal to 0
            Don't care about 1-finger touch cycles which is not deterministic.
        """
        range_fingers = range(1, self.MAX_FINGERS)
        flag_check = self._init_dict(range_fingers, True)
        for f in range_fingers:
            cycles = self._get_event_cycles_for_num_fingers(f)
            if f == num_fingers:
                flag_check[f] = cycles == 1
            elif f > num_fingers:
                flag_check[f] = cycles == 0
        return all(flag_check)

    def get_physical_clicks(self, num_fingers):
        """Get the count of physical clicks for the given number of fingers."""
        flag_fingers_touch = self.verify_exact_number_fingers_touch(num_fingers)
        click_cycles = self._get_event_cycles(self.check_event_func_click)
        return click_cycles if flag_fingers_touch else 0

    def get_raw_physical_clicks(self):
        """Get how many BTN_LEFT click events have been seen.

        When calculating the raw BTN_LEFT click count, this method does not
        consider whether BTN_LEFT comes with the correct finger (tracking) IDs.
        A correct BTN_LEFT click consists of value 1 followed by value 0.
        """
        click_count = 0
        btn_left_was_pressed = False
        for packet in self.packets:
            for event in packet:
                # when seeing BTN_LEFT value: 0 -> 1
                if (MtbEvent.is_BTN_LEFT_value(event, 1) and
                        not btn_left_was_pressed):
                    btn_left_was_pressed = True
                # when seeing BTN_LEFT value: 1 -> 0
                elif (MtbEvent.is_BTN_LEFT_value(event, 0) and
                        btn_left_was_pressed):
                    btn_left_was_pressed = False
                    click_count += 1
        return click_count

    def get_correct_physical_clicks(self, number_fingers):
        """Get the count of physical clicks correctly overlap with
        the given number of fingers.

        @param num_fingers: the expected number of fingers when a physical
                click is seen
        """
        sm = MtbStateMachine()
        correct_click_count = 0
        click_with_correct_number_fingers = False
        for packet in self.packets:
            btn_left_was_pressed = False
            btn_left_was_released = False
            for event in packet:
                sm.add_event(event)
                if MtbEvent.is_BTN_LEFT_value(event, 1):
                    btn_left_was_pressed = True
                elif MtbEvent.is_BTN_LEFT_value(event, 0):
                    btn_left_was_released = True
            sm.get_current_tid_data_for_all_tids()

            # Check the number of fingers only after all events in this packet
            # have been processed.
            if btn_left_was_pressed or btn_left_was_released:
                click_with_correct_number_fingers |= (sm.number_fingers ==
                                                      number_fingers)

            # If BTN_LEFT was released, reset the flag and increase the count.
            if btn_left_was_released and click_with_correct_number_fingers:
                correct_click_count += 1
                click_with_correct_number_fingers = False

        return correct_click_count


class MtbParser:
    """Touch device MTB event Parser."""

    def __init__(self):
        self._get_event_re_patt()

    def _get_event_re_patt(self):
        """Construct the regular expression search pattern of MTB events.

        An ordinary event looks like
          Event: time 133082.748019, type 3 (EV_ABS), code 0 (ABS_X), value 316
        A SYN_REPORT event looks like
          Event: time 10788.289613, -------------- SYN_REPORT ------------
        """
        # Get the pattern of an ordinary event
        event_patt_time = 'Event:\s*time\s*(\d+\.\d+)'
        event_patt_type = 'type\s*(\d+)\s*\(\w+\)'
        event_patt_code = 'code\s*(\d+)\s*\(\w+\)'
        event_patt_value = 'value\s*(-?\d+)'
        event_sep = ',\s*'
        event_patt = event_sep.join([event_patt_time,
                                     event_patt_type,
                                     event_patt_code,
                                     event_patt_value])
        self.event_re_patt = re.compile(event_patt, re.I)

        # Get the pattern of the SYN_REPORT event
        event_patt_type_SYN_REPORT = '-+\s*SYN_REPORT\s-+'
        event_patt_SYN_REPORT = event_sep.join([event_patt_time,
                                                event_patt_type_SYN_REPORT])
        self.event_re_patt_SYN_REPORT = re.compile(event_patt_SYN_REPORT, re.I)

    def _get_event_dict_ordinary(self, line):
        """Construct the event dictionary for an ordinary event."""
        result = self.event_re_patt.search(line)
        ev_dict = {}
        if result is not None:
            ev_dict[MTB.EV_TIME] = float(result.group(1))
            ev_dict[MTB.EV_TYPE] = int(result.group(2))
            ev_dict[MTB.EV_CODE] = int(result.group(3))
            ev_dict[MTB.EV_VALUE] = int(result.group(4))
        return ev_dict

    def _get_event_dict_SYN_REPORT(self, line):
        """Construct the event dictionary for a SYN_REPORT event."""
        result = self.event_re_patt_SYN_REPORT.search(line)
        ev_dict = {}
        if result is not None:
            ev_dict[MTB.EV_TIME] = float(result.group(1))
            ev_dict[MTB.SYN_REPORT] = True
        return ev_dict

    def _get_event_dict(self, line):
        """Construct the event dictionary."""
        EVENT_FUNC_LIST = [self._get_event_dict_ordinary,
                           self._get_event_dict_SYN_REPORT]
        for get_event_func in EVENT_FUNC_LIST:
            ev_dict = get_event_func(line)
            if ev_dict:
                return ev_dict
        return False

    def _is_SYN_REPORT(self, ev_dict):
        """Determine if this event is SYN_REPORT."""
        return ev_dict.get(MTB.SYN_REPORT, False)

    def parse(self, raw_event):
        """Parse the raw event string into a list of event dictionary."""
        ev_list = []
        packets = []
        start_flag = False
        for line in raw_event:
            ev_dict = self._get_event_dict(line)
            if ev_dict:
                start_flag = True
                ev_list.append(ev_dict)
                if self._is_SYN_REPORT(ev_dict):
                    packets.append(ev_list)
                    ev_list = []
            elif start_flag:
                logging.warn('  Warn: format problem in event:\n  %s' % line)
        return packets

    def parse_file(self, file_name):
        """Parse raw device events in the given file name."""
        packets = None
        if os.path.isfile(file_name):
            with open(file_name) as f:
                packets = self.parse(f)
        return packets


if __name__ == '__main__':
    # Read a device file, and convert it to pretty packet format.
    if len(sys.argv) != 2 or not os.path.exists(sys.argv[1]):
        print 'Usage: %s device_file' % sys.argv[0]
        exit(1)

    with open(sys.argv[1]) as event_file:
        packets = MtbParser().parse(event_file)
    for packet in packets:
        print make_pretty_packet(packet)
