#!/usr/bin/env python
import gtk

import ParrotZik
import BluetoothPairedDevices
from SysIndicator import MenuItem
from SysIndicator import Menu
from SysIndicator import SysIndicator

REFRESH_FREQUENCY = 30000
RECONNECT_FREQUENCY = 5000


class repeat(object):
    def __init__(self, f):
        self.f = f
        self.id = None

    def __call__(self, cls):
        self.f(cls)

    def start(self, cls, frequency):
        if not self.id:
            def run():
                self.f(cls)
                return True

            self.id = gtk.timeout_add(frequency, run)

    def stop(self):
        if self.id:
            gtk.timeout_remove(self.id)
            self.id = None


class ParrotZikIndicator(SysIndicator):
    def __init__(self):
 
        self.menu = Menu()

        self.info_item = MenuItem("Parrot Zik Not connected..",
                                  None, sensitive=False)
        self.menu.append(self.info_item)

        self.version_1_interface = ParrotZikVersion1Interface(self)
        self.version_2_interface = ParrotZikVersion2Interface(self)
        self.quit = MenuItem("Quit", gtk.main_quit, checkitem=True)
        self.menu.append(self.quit)

        SysIndicator.__init__(self, icon="zik-audio-headset", menu=self.menu)

        self.active_interface = None

    @repeat
    def reconnect(self):
        if self.active_interface:
            if not self.active_interface.connected:
                print "Lost connection"
                self.active_interface.deactivate()
            else:
                self.reconnect.stop()
        else:
            mac = BluetoothPairedDevices.ParrotZikMac()
            if mac:
                parrot = ParrotZik.connect(mac)
                if parrot.api.sock:
                    if parrot.version.startswith('1'):
                        self.version_1_interface.activate(parrot)
                    else:
                        self.version_2_interface.activate(parrot)
                    self.autorefresh(self)
                    self.autorefresh.start(self, REFRESH_FREQUENCY)
                    self.reconnect.stop()
                    print "Connected"
                else:
                    print "Failed to connect to Parrot Zik %s" % mac

    @repeat
    def autorefresh(self):
        if self.active_interface:
            self.active_interface.refresh()
        else:
            self.reconnect.start(self, RECONNECT_FREQUENCY)
            self.autorefresh.stop()

    def main(self):
        self.reconnect.start(self, RECONNECT_FREQUENCY)
        SysIndicator.main(self)

class ParrotZikBaseInterface(object):
    def __init__(self, indicator):
        self.indicator = indicator
        self.parrot = None
        self.battery_level = MenuItem("Battery Level:", None, sensitive=False,
                                      visible=False)
        self.battery_state = MenuItem("Battery State:", None, sensitive=False,
                                      visible=False)
        self.firmware_version = MenuItem("Firmware Version:", None,
                                         sensitive=False, visible=False)
        self.auto_connection = MenuItem("Auto Connection", self.toggleAuto,
                                        checkitem=True, visible=False)
        self.indicator.menu.append(self.battery_level)
        self.indicator.menu.append(self.battery_state)
        self.indicator.menu.append(self.firmware_version)
        self.indicator.menu.append(self.auto_connection)

    @property
    def connected(self):
        if self.parrot:
            return self.parrot.api.sock
        else:
            return False

    def activate(self, parrot):
        self.parrot = parrot
        self.battery_level.show()
        self.battery_state.show()
        self.firmware_version.show()
        self.auto_connection.show()

        self.name = self.parrot.friendly_name
        self.version = self.parrot.version

        self.auto_connection.set_active(self.parrot.auto_connect)

        self.indicator.active_interface = self
        self.indicator.menu.reposition()

    def deactivate(self):
        self.parrot = None
        self.battery_level.hide()
        self.battery_state.hide()
        self.firmware_version.hide()
        self.auto_connection.hide()
        self.indicator.setIcon("zik-audio-headset")
        self.indicator.info_item.set_label("Parrot Zik Not connected..")
        self.indicator.menu.reposition()
        self.indicator.active_interface = None

    def toggleAuto(self, widget):
        if self.connected:
            self.parrot.auto_connection = self.auto_connection.get_active()
            self.auto_connection.set_active(self.parrot.auto_connection)

    def refresh(self):
        raise NotImplementedError


class ParrotZikVersion1Interface(ParrotZikBaseInterface):
    def __init__(self, indicator):
        super(ParrotZikVersion1Interface, self).__init__(indicator)
        self.noise_cancelation = MenuItem("Noise Cancellation", self.toggleANC,
                                          checkitem=True, visible=False)
        self.lou_reed_mode = MenuItem("Lou Reed Mode", self.toggleLouReedMode,
                                      checkitem=True, visible=False)
        self.concert_hall_mode = MenuItem(
            "Concert Hall Mode", self.toggleParrotConcertHall,
            checkitem=True, visible=False)
        self.indicator.menu.append(self.noise_cancelation)
        self.indicator.menu.append(self.lou_reed_mode)
        self.indicator.menu.append(self.concert_hall_mode)

    def activate(self, parrot):
        self.noise_cancelation.show()
        self.lou_reed_mode.show()
        self.concert_hall_mode.show()
        super(ParrotZikVersion1Interface, self).activate(parrot)

        self.noise_cancelation.set_active(self.parrot.noise_cancel)
        self.lou_reed_mode.set_active(self.parrot.lou_reed_mode)
        self.concert_hall_mode.set_active(self.parrot.concert_hall)

    def deactivate(self):
        self.noise_cancelation.hide()
        self.lou_reed_mode.hide()
        self.concert_hall_mode.hide()
        super(ParrotZikVersion1Interface, self).deactivate()

    def toggleANC(self, widget):
        if self.connected:
            self.parrot.noise_cancel = self.noise_cancelation.get_active()
            self.noise_cancelation.set_active(self.parrot.noise_cancel)

    def toggleLouReedMode(self, widget):
        if self.connected:
            self.parrot.lou_reed_mode = self.lou_reed_mode.get_active()
            self.lou_reed_mode.set_active(self.parrot.lou_reed_mode)
            self.concert_hall_mode.set_active(self.parrot.concert_hall)
            self.concert_hall_mode.set_sensitive(
                not self.lou_reed_mode.get_active())

    def toggleParrotConcertHall(self, widget):
        if self.connected:
            self.parrot.concert_hall = self.concert_hall_mode.get_active()
            self.concert_hall_mode.set_active(self.parrot.concert_hall)

    def refresh(self):
        if self.connected:
            print "Updating battery"
            self.batteryLevel = int(self.parrot.battery_level)

            if self.parrot.BatteryCharging:
                self.batteryLevel = "Charging"
                self.indicator.setIcon("zik-battery-charging")
                self.batteryLevel = "Unknown"
                self.batteryState = "Charging"
            elif self.batteryLevel > 80:
                self.indicator.setIcon("zik-battery-100")
                self.batteryState = "In Use"
            elif self.batteryLevel > 60:
                self.indicator.setIcon("zik-battery-080")
                self.batteryState = "In Use"
            elif self.batteryLevel > 40:
                self.indicator.setIcon("zik-battery-060")
                self.batteryState = "In Use"
            elif self.batteryLevel > 20:
                self.indicator.setIcon("zik-battery-040")
                self.batteryState = "In Use"
            else:
                self.indicator.setIcon("zik-battery-low")
                self.batteryState = "In Use"

            self.indicator.info_item.set_label("Connected to: " + self.name)
            self.firmware_version.set_label(
                "Firmware version: " + self.version)
            self.battery_state.set_label("State: " + self.batteryState)
            self.battery_level.set_label(
                "Battery Level: " + str(self.batteryLevel))
        else:
            self.deactivate()


class ParrotZikVersion2Interface(ParrotZikBaseInterface):
    def __init__(self, indicator):
        super(ParrotZikVersion2Interface, self).__init__(indicator)
        self.noise_cancelation = MenuItem("Noise Cancellation", None,
                                          sensitive=True, visible=False)
        self.noise_cancelation_submenu = Menu()
        self.noise_cancelation.set_submenu(self.noise_cancelation_submenu)

        self.noise_cancelation_enabled = MenuItem("Enabled", self.toggleANC,
                                                  sensitive=False, checkitem=True)
        self.noise_cancelation_mode0 = MenuItem("Mode0", self.toggledummy,
                                                sensitive=False, checkitem=True)
        self.noise_cancelation_mode1 = MenuItem("Mode1", self.toggledummy,
                                                sensitive=False, checkitem=True)
        self.noise_cancelation_mode2 = MenuItem("Mode2", self.toggledummy,
                                                sensitive=False, checkitem=True)
        self.noise_cancelation_mode3 = MenuItem("Mode3", self.toggledummy,
                                                sensitive=False, checkitem=True)
        self.noise_cancelation_submenu.append(self.noise_cancelation_enabled)
        self.noise_cancelation_submenu.append(self.noise_cancelation_mode0)
        self.noise_cancelation_submenu.append(self.noise_cancelation_mode1)
        self.noise_cancelation_submenu.append(self.noise_cancelation_mode2)
        self.noise_cancelation_submenu.append(self.noise_cancelation_mode3)
        self.indicator.menu.append(self.noise_cancelation)

        self.concert_hall_mode = MenuItem(
            "Sound Mode", None, sensitive=True, checkitem=False, visible=False)
        self.concert_hall_mode_submenu = Menu()
        self.concert_hall_mode.set_submenu(self.concert_hall_mode_submenu)

        self.concert_hall_mode_enabled = MenuItem("Enabled", None,
                                                  sensitive=True, checkitem=True)
        self.concert_hall = MenuItem("Concert Hall", None,
                                     sensitive=True, checkitem=True)
        self.jazz_mode = MenuItem("Jazz Club", None,
                                  sensitive=True, checkitem=True)
        self.living_mode = MenuItem("Libing Room", None,
                                    sensitive=True, checkitem=True)
        self.silent_mode = MenuItem("Silent Room", None,
                                    sensitive=True, checkitem=True)
        self.concert_hall_mode_submenu.append(self.concert_hall_mode_enabled)
        self.concert_hall_mode_submenu.append(self.concert_hall)
        self.concert_hall_mode_submenu.append(self.jazz_mode)
        self.concert_hall_mode_submenu.append(self.living_mode)
        self.concert_hall_mode_submenu.append(self.silent_mode)
        self.indicator.menu.append(self.concert_hall_mode)

        self.flight_mode = MenuItem("Flight Mode", None,
                                    sensitive=True, checkitem=True, visible=False)
        self.indicator.menu.append(self.flight_mode)

    def activate(self, parrot):
        self.noise_cancelation.show()
        self.concert_hall_mode.show()
        self.flight_mode.show()
        super(ParrotZikVersion2Interface, self).activate(parrot)
        self.noise_cancelation_enabled.set_active(self.parrot.noise_cancel)
        # self.flight_mode.set_active(self.parrot.flight_mode)

    def toggleANC(self, widget):
        if self.connected:
            self.parrot.noise_cancel = self.noise_cancelation.get_active()
            self.noise_cancelation.set_active(self.parrot.noise_cancel)

    def toggledummy(self, widget):
        print(widget.get_name())

    def refresh(self):
        if self.connected:
            print "Updating battery"
            self.batteryLevel = int(self.parrot.battery_level)

            if self.parrot.BatteryCharging:
                self.batteryLevel = "Charging"
                self.indicator.setIcon("zik-battery-charging")
                self.batteryLevel = "Unknown"
                self.batteryState = "Charging"
            elif self.batteryLevel > 80:
                self.indicator.setIcon("zik-battery-100")
                self.batteryState = "In Use"
            elif self.batteryLevel > 60:
                self.indicator.setIcon("zik-battery-080")
                self.batteryState = "In Use"
            elif self.batteryLevel > 40:
                self.indicator.setIcon("zik-battery-060")
                self.batteryState = "In Use"
            elif self.batteryLevel > 20:
                self.indicator.setIcon("zik-battery-040")
                self.batteryState = "In Use"
            else:
                self.indicator.setIcon("zik-battery-low")
                self.batteryState = "In Use"

            self.indicator.info_item.set_label("Connected to: " + self.name)
            self.firmware_version.set_label(
                "Firmware version: " + self.version)
            self.battery_state.set_label("State: " + self.batteryState)
            self.battery_level.set_label(
                "Battery Level: " + str(self.batteryLevel))
        else:
            self.deactivate()

if __name__ == "__main__":
    indicator = ParrotZikIndicator()
    indicator.main()