import logging
import sys

from django.core.urlresolvers import reverse
from django.shortcuts import render
from django.utils.html import escapejs
from django.utils.translation import ugettext as _

from freenasUI.freeadmin.hook import AppHook
from freenasUI.failover.mixins import FailoverAlert
from freenasUI.failover.notifier import FailoverNotifier

log = logging.getLogger('failover.hook')


class FailoverHook(AppHook):

    name = 'failover'

    def _common_failover_view(self, request):
        from freenasUI.middleware.notifier import notifier
        from freenasUI.failover.models import Failover
        status = notifier().failover_status()
        enabled = Failover.objects.all().exists()
        if enabled and status != 'MASTER':
            qs = Failover.objects.order_by('-id')
            if qs.exists():
                failover = qs[0]
            else:
                failover = None
            return render(request, "failover/failover.html", {
                'failover': failover,
            })

    def _common_ha_abort(self):
        from freenasUI.middleware.notifier import notifier
        from freenasUI.failover.models import Failover
        """
        This method detects whether this unit is part of a HA pair
        and if so whether it is active or passive.  If this is
        HA and passive returns True.
        If this is currently the master of an HA pair or not
        in an HA pair it returns False.
        """

        status = notifier().failover_status()
        failover = Failover.objects.all().exists()
        if failover and status != "MASTER":
            return True
        return False

    def _common_sync(self, events):
        from freenasUI.middleware.notifier import notifier
        from freenasUI.failover.models import Failover
        qs = Failover.objects.order_by('-id')
        if qs.exists() and notifier().failover_status() == 'MASTER':
            events.append('sync_to_peer(%d)' % qs[0].id)

    def _common_nav_init(self, tree_roots, nav):
        from freenasUI.middleware.notifier import notifier
        from freenasUI.failover.models import Failover
        status = notifier().failover_status()
        enabled = Failover.objects.all().exists()
        if enabled and status != 'MASTER':
            tree_roots.unregister(nav)

    def base_js(self, request):
        return [
            'lib/js/failover.js',
        ]

    def base_css(self, request):
        return [
            'css/failover.css',
        ]

    def hook_app_index_storage(self, request):
        return self._common_failover_view(request)

    def hook_app_index_sharing(self, request):
        return self._common_failover_view(request)

    def hook_app_index_services(self, request):
        return self._common_failover_view(request)

    def hook_app_index_reporting(self, request):
        return self._common_failover_view(request)

    def hook_app_tabs_network(self, request):
        return [
            {
                'name': 'CARP',
                'focus': 'network.CARP.View',
                'verbose_name': _('CARP'),
                'url': reverse('freeadmin_failover_carp_datagrid'),
            }
        ]

    def hook_app_tabs_system(self, request):
        return [
            {
                'name': 'Failovers',
                'focus': 'system.Failover.View',
                'verbose_name': _('Failovers'),
                'url': reverse('freeadmin_failover_failover_datagrid'),
            }
        ]

    def hook_app_tabs_storage(self, request):
        return [
            {
                'name': 'HAReplication',
                'focus': 'storage.HAReplication',
                'verbose_name': _('HA Replication'),
                'url': '%s?deletable=false' % reverse('storage_hareplication'),
            }
        ]

    def hook_class_new_VolumeStatusAlert(self, bases, attrs):
        bases.insert(0, FailoverAlert)

    def hook_class_new_notifier(self, bases, attrs):
        bases.insert(0, FailoverNotifier)

    def hook_form_buttons_AdvancedForm(self, form, action, *args, **kwargs):
        from freenasUI.middleware.notifier import notifier
        from freenasUI.failover.models import Failover
        btns = []
        status = notifier().failover_status()
        failovers = Failover.objects.all()
        if len(failovers) > 0 and status != 'MASTER':
            for failover in failovers:
                try:
                    notifier().zpool_parse(failover.volume.vol_name)
                except:
                    btns.append({
                        'name': 'ForceMaster',
                        'verbose_name': _('Failover Force Master'),
                        'onclick': 'failoverForceMaster(this, "%s")' % (
                            escapejs(reverse('failover_force_master'))
                        ),
                    })
                    break
        return btns

    def hook_form_done(self, cname, form, request, events):
        if cname in (
            'AFP_ShareForm', 'CIFS_ShareForm', 'NFS_ShareForm',
            'ActiveDirectoryForm',
            'AFPForm',
            'CARPForm',
            'CIFSForm', 'DynamicDNSForm', 'DomainControllerForm',
            'iSCSITargetAuthCredentialForm', 'iSCSITargetToExtentForm',
            'iSCSITargetGlobalConfigurationForm', 'iSCSITargetExtentForm',
            'iSCSITargetPortalForm', 'iSCSITargetAuthorizedInitiatorForm',
            'iSCSITargetForm',
            'FailoverForm',
            'FTPForm', 'LDAPForm',
            'LicenseUpdateForm',
            'LLDPForm', 'NFSForm', 'NIS', 'NT4',
            'PeriodicSnapForm', 'ReplicationForm',
            'RsyncdForm', 'RsyncModForm', 'SMARTForm', 'SNMPForm', 'SSHForm',
            'servicesForm', 'TFTPForm', 'UPSForm',
            'VolumeManagerForm',
        ):
            self._common_sync(events)

    def hook_form_delete(self, cname, form, request, events):
        if cname in (
            'AFP_ShareForm', 'CIFS_ShareForm', 'NFS_ShareForm',
            'ActiveDirectoryForm',
            'AFPForm',
            'CARPForm',
            'CIFSForm', 'DynamicDNSForm', 'DomainControllerForm',
            'iSCSITargetAuthCredentialForm', 'iSCSITargetToExtentForm',
            'iSCSITargetGlobalConfigurationForm', 'iSCSITargetExtentForm',
            'iSCSITargetPortalForm', 'iSCSITargetAuthorizedInitiatorForm',
            'iSCSITargetForm',
            'FailoverForm',
            'FTPForm', 'LDAPForm', 'LLDPForm', 'NFSForm', 'NIS', 'NT4',
            'PeriodicSnapForm', 'ReplicationForm',
            'RsyncdForm', 'RsyncModForm', 'SMARTForm', 'SNMPForm', 'SSHForm',
            'servicesForm', 'TFTPForm', 'UPSForm',
        ):
            self._common_sync(events)

    def hook_nav_init_storage(self, tree_roots, nav, request):
        self._common_nav_init(tree_roots, nav)

    def hook_nav_init_sharing(self, tree_roots, nav, request):
        self._common_nav_init(tree_roots, nav)

    def hook_nav_init_services(self, tree_roots, nav, request):
        self._common_nav_init(tree_roots, nav)

    def hook_tool_run_autorepl(self):
        if self._common_ha_abort():
            sys.exit(0)

    def hook_tool_run_autosnap(self):
        if self._common_ha_abort():
            sys.exit(0)

    def top_menu(self, request):
        from freenasUI.middleware.notifier import notifier
        from freenasUI.failover.models import Failover

        enabled = Failover.objects.all().exists()
        if not enabled:
            return []
        if not hasattr(notifier, 'failover_status'):
            return []
        status = notifier().failover_status()
        if status == 'MASTER':
            name = _('Active')
        else:
            name = _('Passive')
        return [
            {
                'id': 'failover_menuitem',
                'name': (
                    '<span id="failover_status_name" status="%s">%s</span>' % (
                        status,
                        name,
                    )
                ),
                'img': (
                    '<div data-dojo-type="dijit.layout.ContentPane" '
                    'id="failover_status" class="%s"></div>' % (
                        'failover_ok'
                        if status == 'MASTER' else 'failover_error'
                    )
                ),
                'onclick': '',
                'align': 'right',
                'weight': 0,
            },
        ]
