#! /usr/local/bin/python

# Copyright C 2002-2003 by Isilon Systems, Inc. All rights not expressly
# granted herein are reserved.
# Created in the United States of America.
# 
# This digital media is protected by U.S. and international copyright and
# intellectual property laws. Unless otherwise specified, all information
# and screens appearing as part of this digital medium, including
# software, services, documents, text, images, icons, and logos design;
# the selection, assembly, arrangement, and design thereof; and the code
# that enables its presentation, are the sole property of Isilon Systems,
# Inc.
# 
# Except as otherwise required by applicable law, no part of any
# copyrighted material may be reproduced, modified, translated,
# distributed, published, or transmitted by any means, electronic or
# mechanical, for any purpose, without the prior written consent of Isilon
# Systems. 
#  
# Isilon and Isilon Systems are registered trademarks of Isilon Systems,
# Inc.  Legion is a trademark of Isilon Systems, Inc.  All other
# trademarks and registered trademarks are the property of their
# respective holders.

import os
import sys
import signal
import getopt

import isi.misc as misc
import isi.ui.lcd.screens as screens
import isi.ui.lcd.library as lcd
import isi.celog.celog_config_api
from isi.config.brand import brand
import isi.config.mcp as mcp
from isi.ui.lib.supportiq_config import SupportIQConfig

ALERT_FILE = '/var/run/supportAlerts.txt'
DEFAULT_ANS = 'yes'
ANS_YES = 'yes'
ANS_NO = 'no'
DELIM = '::'

# Create a global celog_cfg object
celog_cfg = isi.celog.celog_config_api.CelogConfigAPI()

# This function will enable the following: SMTP notifications,
# the SupportIQ Agent, notifications via SupportIQ Agent,
# remote script access for the SupportIQ Agent
def enable_supportIQ(company, contact, phone, email):

    # Save primary contact info
    new_contact_settings = {}
    if company:
        new_contact_settings['company'] = company
    if contact:
        new_contact_settings['primary_name'] = contact
    if phone:
        new_contact_settings['primary_phone1'] = phone
    if email:
        new_contact_settings['primary_email'] = email
    if new_contact_settings:
        celog_cfg.set_contact_settings(new_contact_settings)

    # Notifications
    celog_cfg.enable_isilonsupport_notifications()
    celog_cfg.enable_supportiq_notifications()

    # SupportIQ service
    SERVICE_NAME = 'supportiq'
    if not get_service_state(SERVICE_NAME):
        enable_service(SERVICE_NAME)

    # SupportIQ remote scripts
    supportIQ_cfg = SupportIQConfig()
    if not supportIQ_cfg.remote_script_enable:
        supportIQ_cfg.set_remote_script_enable(True)
        supportIQ_cfg.save()

# This function will disable the following: SMTP notifications,
# the SupportIQ Agent, notifications via SupportIQ Agent,
# remote script access for the SupportIQ Agent
def disable_supportIQ():
    # Notifications
    celog_cfg.disable_isilonsupport_notifications()
    celog_cfg.disable_supportiq_notifications()

    # SupportIQ service
    SERVICE_NAME = 'supportiq'
    if get_service_state(SERVICE_NAME):
        disable_service(SERVICE_NAME)

    # SupportIQ remote scripts
    supportIQ_cfg = SupportIQConfig()
    if supportIQ_cfg.remote_script_enable:
        supportIQ_cfg.set_remote_script_enable(False)
        supportIQ_cfg.save()

def get_service_state(service_name):
    mcpconfig = mcp.mcpconfig()
    mcpconfig.showall()
    return bool(mcpconfig.get(service_name)['enabled'])

def disable_service(service_name):
    mcpconfig = mcp.mcpconfig()
    mcpconfig.showall()
    mcpconfig.disable(service_name)

def enable_service(service_name):
    mcpconfig = mcp.mcpconfig()
    mcpconfig.showall()
    mcpconfig.enable(service_name)

def get_contact_settings():
    # Get the current contact settings
    return celog_cfg.get_contact_settings()

def save_prompt(ans, info):

    # Save info to a file
    fd = open(ALERT_FILE, 'w')
    fd.write('answer%s%s\n' % (DELIM, ans))
    if info:
        fd.write('company%s%s\n' % (DELIM, info['company']))
        fd.write('contact%s%s\n' % (DELIM, info['contact']))
        fd.write('phone%s%s\n' % (DELIM, info['phone']))
        fd.write('email%s%s\n' % (DELIM, info['email']))
    fd.close()

def commit():
    if not misc.ifs_mounted():
        return

    # Default values
    exists = True
    ans = ANS_YES
    company = None
    contact = None
    phone = None
    email = None

    # Attempt to read ALERT_FILE
    try:
        fd = open(ALERT_FILE, 'r')
        
        for line in fd.readlines():
            line = line.rstrip()
            key, val = line.split(DELIM)
            if key == 'answer':
                ans = val
            elif key == 'company':
                company = val
            elif key == 'contact':
                contact = val
            elif key == 'phone':
                phone = val
            elif key == 'email':
                email = val

    except IOError:
        # No file means don't do anything.
        return

    try:
        if ans.startswith(ANS_YES):
            enable_supportIQ(company, contact, phone, email)
        else:
            disable_supportIQ()

        if exists:
            os.unlink(ALERT_FILE)
    except Exception as e:
        print "Unable to set support alerts: %s" % e

def handle_lcd():

    try:
        screen = screens.ListInputScreen(
                'Send alerts to ' + brand('company') + '?', ['yes', 'no'])
        screen.CAN_CANCEL = False
        screen.CAN_EXIT = False
        result = lcd.show(screen)
        if result == 'yes':
            save_prompt(ANS_YES, None)
        else:
            save_prompt(ANS_NO, None)
        commit()

        return 1
    except:
        return 0

def prompt_info(prompt, required = False):
    done = 0
    val = ''

    while not done:
        # Note that KeyboardInterrupt is handled elsewhere
        val = raw_input(prompt)
        if not required or val:
            done = 1

    return val

def show_current_settings():
    '''Show the current configuration'''

    # Get the current contact settings
    contact_settings = get_contact_settings()

    print "\n\tCurrent SupportIQ Settings:"

    # Show SupportIQ status
    siq_status = "Disabled"
    if 'SupportIQ' in celog_cfg.get_notification_settings():
        siq_status = "Enabled"
    print "\n\t%-20s: %s\n" % ("SupportIQ enabled:", siq_status)

    # Show contact status
    print "\t%-20s: %s" % ("Company", contact_settings['company'])
    print "\t%-20s: %s" % ("Location", contact_settings['location'])
    print "\t%-20s: %s" % ("Primary Name", contact_settings['primary_name'])
    print "\t%-20s: %s" % ("Phone", contact_settings['primary_phone1'])
    print "\t%-20s: %s" % ("Email", contact_settings['primary_email'])
    print "\t%-20s: %s" % ("Phone 2", contact_settings['primary_phone2'])
    print "\t%-20s: %s" % ("Secondary Name", contact_settings['secondary_name'])
    print "\t%-20s: %s" % \
            ("Secondary Phone", contact_settings['secondary_phone1'])
    print "\t%-20s: %s" % \
            ("Secondary Phone 2", contact_settings['secondary_phone2'])
    print "\t%-20s: %s" % \
            ("Secondary Email", contact_settings['secondary_email'])
    print "\n"

def handle_console(extra):
    """
    extra - Collect extra information (i.e. alert contact information)
    """

    # Get the current contact settings
    contact_settings = get_contact_settings()

    done = 0
    val = ''

    while not done:
        done = 1    # assume this will only run once

        question = "Would you like to enable SupportIQ? [%s] " % DEFAULT_ANS
        try:
            val = raw_input(question)
        except KeyboardInterrupt:
            break
        
        if val == '':
            val = DEFAULT_ANS 
        if val == 'yes' or val == 'y':
            # Defaults

            # Prompt for contact information
            if extra:
                info = {}
                info['company'] = ''
                info['contact'] = ''
                info['phone'] = ''
                info['email'] = ''

                # Don't require the company to be updated if it's already set
                update = False if contact_settings['company'] else True

                try:
                    print "\nEdit contact information (RETURN to keep " + \
                            "current setting):"
                    info['company'] = \
                            prompt_info('Please enter company name (%s): '
                            % contact_settings['company'], update)
                    info['contact'] = \
                            prompt_info('Please enter contact name (%s): '
                            % contact_settings['primary_name'])
                    info['phone'] = \
                            prompt_info('Please enter contact phone (%s): '
                            % contact_settings['primary_phone1'])
                    info['email'] = \
                            prompt_info('Please enter contact email (%s): '
                            % contact_settings['primary_email'])
                except KeyboardInterrupt:
                    pass

                save_prompt(ANS_YES, info)
            else:
                save_prompt(ANS_YES, None)

        elif val != 'no' and val != 'n':
            print ""
            print "Please enter one of 'yes' or 'no'"
            print ""
            done = 0
        else:
            save_prompt(ANS_NO, None)

        # If interrupted, done is 0.
        if done:
            commit()

    return 1 # Always kill LCD.

def alert_prompt(extra):
    def handle_signal(signal, stack_frame):
        sys.exit(0)
    
    def kill_other(pid):
        try:
            os.kill(pid, signal.SIGINT)
        except os.error:
            pass

    pid = os.fork()
    # We use SIGINT here, because raw_input blocks SIGTERM
    signal.signal(signal.SIGINT, handle_signal)

    done = 0

    if pid == 0:
        pid = os.getppid()
        #Close fds
        for i in range(0,3):
            os.close(i)
        sys.stdout = open('/dev/null', 'w')
        sys.stdin = open('/dev/null', 'r')
        sys.stderr = open('/dev/null', 'w')

        done = handle_lcd()
    else:
        done = handle_console(extra)

    if done:
        kill_other(pid)

def main(argv):

    def usage():
        print "Usage: isi_promptsupport [-e] [-c] [-s]"
        print ""
        print "Configure SupportIQ settings:"
        print ""
        print "Options:"
        print "  -e\t\tEdit primary contact information"
        print "  -c\t\tCommit changes without prompting for information"
        print "  -s\t\tShow current configuration"

    try:
        opts, args = getopt.getopt(argv, 'ecs')
    except Exception:
        usage()
        return 1

    extra = False
    do_commit = False
    show_current = False

    # Parse arguments; 
    for (opt, arg) in opts:
        if opt == '-e':
            extra = True
        if opt == '-c':
            do_commit = True
        if opt == '-s':
            show_current = True
  
    try:
        if show_current:
            show_current_settings()
        elif do_commit:
            commit()
        else:
            alert_prompt(extra)
        return 0
    except:
        # XXX This raise is intentional, for now, to aid in bug-fixing.
        raise
        return -1

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
