#!/usr/bin/env python

# Copyright (C) 2005-2007 INdT - Instituto Nokia de Tecnologia
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

__author__ = "Artur Duque de Souza"
__author_email__ = "artur.souza@openbossa.org"
__license__ = "GPL"

import logging
import os

from canolad.mount_table import MountTable
from pyinotify import EventsCodes, ProcessEvent

class Pmtab(ProcessEvent):
    mount_file = "/etc/mtab"
    log = logging.getLogger("canola.daemon.pmtab")

    def __init__(self, wm, cb_dev_added=None, cb_dev_removed=None, cb_db_locked=None, cb_db_unlocked=None):
        ProcessEvent.__init__(self)
        self.wm = wm
        self.mount_table = MountTable(cb_db_locked, cb_db_unlocked)

        self._started_monitor = False
        self.mask = EventsCodes.IN_MODIFY | EventsCodes.IN_DELETE_SELF
        self.log.info("Started Canola-Daemon with Inotify support")

    def start_monitoring(self):
        # take a look on mount_file to discover what is already mounted
        # and start monitoring
        if not self._started_monitor:
            self.watches = self.wm.add_watch(self.mount_file, self.mask)
            self.read_mount_file()
            self._started_monitor = True

    def read_mount_file(self):
        def parse_line(line):
            fields = line.split(" ")
            # dev, mount_point, type
            if fields[1].find("/media") >= 0:
                return (fields[0], fields[1], fields[2])
            return None

        mtab = open(self.mount_file)
        lines = mtab.readlines()
        mtab.close()

        self.log.debug("Reading mount file: %s", self.mount_file)
        for line in lines:
            dev = parse_line(line)
            if dev and not self.mount_table.has_key(dev[1]):
                path = os.path.join(dev[1], ".")
                self.watches.update(self.wm.add_watch(path,
                                                      EventsCodes.IN_DELETE_SELF,
                                                      auto_add=True))
                self.log.debug("Watches: %s", self.watches)
                self.mount_table[dev[1]] = dev
        return True

    def process_IN_MODIFY(self, event):
        # Mounting device
        self.read_mount_file()
        self.log.debug("Modified file")
        self.log.debug(self.mount_table)
        return True

    def process_IN_DELETE_SELF(self, event):
        try:
            self.wm.rm_watch(self.watches[event.path])
            self.watches.pop(event.path)
        except:
            pass

        try:
            self.watches.update(self.wm.add_watch(self.mount_file, self.mask))
        except:
            pass
        return True

    def process_IN_UNMOUNT(self, event):
        # Unmounting device
        dev = self.mount_table.pop(event.path, None)
        self.watches.pop(os.path.join(dev[1], "."))
        self.log.debug("Removed device: %s" % dev[0])
        self.log.debug(self.mount_table)
        return True

    def process_default(self, event):
        # ignore other events
        pass
