#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#     ||          ____  _ __
#  +------+      / __ )(_) /_______________ _____  ___
#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
#
#  Copyright (C) 2011-2013 Bitcraze AB
#
#  Crazyflie Nano Quadcopter Client
#
#  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 Street, Fifth Floor, Boston, MA  02110-1301, USA.

"""
The main file for the Crazyflie control application.
"""
__author__ = 'Bitcraze AB'
__all__ = ['MainUI']

import sys
import logging


logger = logging.getLogger(__name__)

from PyQt4 import QtGui, uic
from PyQt4.QtCore import pyqtSignal, Qt, pyqtSlot, QDir, QUrl
from PyQt4.QtGui import QLabel, QActionGroup, QMessageBox, QAction, QDesktopServices

from dialogs.connectiondialogue import ConnectDialogue
from dialogs.inputconfigdialogue import InputConfigDialogue
from dialogs.cf2config import Cf2ConfigDialog
from dialogs.cf1config import Cf1ConfigDialog
from cflib.crazyflie import Crazyflie
from dialogs.logconfigdialogue import LogConfigDialogue

from cfclient.utils.input import JoystickReader
from cfclient.utils.config import Config
from cfclient.utils.logconfigreader import LogConfigReader
from cfclient.utils.config_manager import ConfigManager

import cfclient.ui.toolboxes
import cfclient.ui.tabs
import cflib.crtp

from cflib.crazyflie.log import Log, LogVariable, LogConfig

from cfclient.ui.dialogs.bootloader import BootloaderDialog
from cfclient.ui.dialogs.about import AboutDialog

from cflib.crazyflie.mem import MemoryElement

(main_window_class,
main_windows_base_class) = (uic.loadUiType(sys.path[0] +
                                           '/cfclient/ui/main.ui'))


class MyDockWidget(QtGui.QDockWidget):
    closed = pyqtSignal()

    def closeEvent(self, event):
        super(MyDockWidget, self).closeEvent(event)
        self.closed.emit()


class UIState:
    DISCONNECTED = 0
    CONNECTING = 1
    CONNECTED = 2


class MainUI(QtGui.QMainWindow, main_window_class):

    connectionLostSignal = pyqtSignal(str, str)
    connectionInitiatedSignal = pyqtSignal(str)
    batteryUpdatedSignal = pyqtSignal(int, object, object)
    connectionDoneSignal = pyqtSignal(str)
    connectionFailedSignal = pyqtSignal(str, str)
    disconnectedSignal = pyqtSignal(str)
    linkQualitySignal = pyqtSignal(int)

    _input_device_error_signal = pyqtSignal(str)
    _input_discovery_signal = pyqtSignal(object)
    _log_error_signal = pyqtSignal(object, str)

    def __init__(self, *args):
        super(MainUI, self).__init__
(*args)
        self.setupUi(self)
        
        ######################################################
        ### By lxrocks

        ### 'Skinny Progress Bar' tweak for Yosemite
        ### Tweak progress bar - artistic I am not - so pick your own colors !!!
        ### Only apply to Yosemite
        ######################################################
        import platform
        if platform.system() == 'Darwin':
        
            (Version,junk,machine) =  platform.mac_ver()
            logger.info("This is a MAC - checking if we can apply Progress Bar Stylesheet for Yosemite Skinny Bars ")
            yosemite = (10,10,0)
            tVersion = tuple(map(int, (Version.split("."))))
            
            if tVersion >= yosemite:
                logger.info( "Found Yosemite:")
        
                tcss = """
                    QProgressBar {
                    border: 2px solid grey;
                    border-radius: 5px;
                    text-align: center;
                }
                QProgressBar::chunk {
                     background-color: #05B8CC;
                 }
                 """
                self.setStyleSheet(tcss)
                
            else:
                logger.info( "Pre-Yosemite")
        
        ######################################################
        
        self.cf = Crazyflie(ro_cache=sys.path[0] + "/cflib/cache",
                            rw_cache=sys.path[1] + "/cache")

        cflib.crtp.init_drivers(enable_debug_driver=Config()
                                                .get("enable_debug_driver"))

        # Create the connection dialogue
        self.connectDialogue = ConnectDialogue()

        # Create and start the Input Reader
        self._statusbar_label = QLabel("Loading device and configuration.")
        self.statusBar().addWidget(self._statusbar_label)

        self.joystickReader = JoystickReader()
        self._active_device = ""
        self.configGroup = QActionGroup(self._menu_mappings, exclusive=True)
        self._load_input_data()
        ConfigManager().conf_needs_reload.add_callback(self._reload_configs)

        # Connections for the Connect Dialogue
        self.connectDialogue.requestConnectionSignal.connect(self.cf.open_link)

        self.cf.connection_failed.add_callback(self.connectionFailedSignal.emit)
        self.connectionFailedSignal.connect(self._connection_failed)
        
        
        self._input_device_error_signal.connect(self._display_input_device_error)
        self.joystickReader.device_error.add_callback(
                        self._input_device_error_signal.emit)
        self._input_discovery_signal.connect(self.device_discovery)
        self.joystickReader.device_discovery.add_callback(
                        self._input_discovery_signal.emit)

        # Connect UI signals
        self.menuItemConnect.triggered.connect(self._connect)
        self.logConfigAction.triggered.connect(self._show_connect_dialog)
        self.connectButton.clicked.connect(self._connect)
        self.quickConnectButton.clicked.connect(self._quick_connect)
        self.menuItemQuickConnect.triggered.connect(self._quick_connect)
        self.menuItemConfInputDevice.triggered.connect(self._show_input_device_config_dialog)
        self.menuItemExit.triggered.connect(self.closeAppRequest)
        self.batteryUpdatedSignal.connect(self._update_vbatt)
        self._menuitem_rescandevices.triggered.connect(self._rescan_devices)
        self._menuItem_openconfigfolder.triggered.connect(self._open_config_folder)

        self._auto_reconnect_enabled = Config().get("auto_reconnect")
        self.autoReconnectCheckBox.toggled.connect(
                                              self._auto_reconnect_changed)
        self.autoReconnectCheckBox.setChecked(Config().get("auto_reconnect"))
        
        self.joystickReader.input_updated.add_callback(
                                         self.cf.commander.send_setpoint)

        # Connection callbacks and signal wrappers for UI protection
        self.cf.connected.add_callback(self.connectionDoneSignal.emit)
        self.connectionDoneSignal.connect(self._connected)
        self.cf.disconnected.add_callback(self.disconnectedSignal.emit)
        self.disconnectedSignal.connect(
                        lambda linkURI: self._update_ui_state(UIState.DISCONNECTED,
                                                        linkURI))
        self.cf.connection_lost.add_callback(self.connectionLostSignal.emit)
        self.connectionLostSignal.connect(self._connection_lost)
        self.cf.connection_requested.add_callback(
                                         self.connectionInitiatedSignal.emit)
        self.connectionInitiatedSignal.connect(
                           lambda linkURI: self._update_ui_state(UIState.CONNECTING,
                                                           linkURI))
 