#!/usr/bin/env python3

import sys
import json
import os, re
import validate
import socket
import struct
import subprocess
import getpass

def cidr(prefix):
    return socket.inet_ntoa(struct.pack(">I", (0xffffffff << (32 - prefix)) & 0xffffffff))

def is_service_running(name):
    output = os.system('ps -A')
    if name in output:
        return True
    return False

def cmd_exists(cmd):
    return subprocess.call("type " + cmd, shell=True,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0

def prompt(type, message, errormessage, isvalid):
    """Prompt for input given a message and return that value after verifying the input.

    Keyword arguments:
    type -- type of input expected.
    message -- the message to display when asking the user for the value
    errormessage -- the message to display when the value fails validation
    isvalid -- a function that returns True if the value given by the user is valid
    """
    res = None
    while res is None:
        res = input(str(message)+': ')
        try:
            res = type(res)
        except ValueError:
            print(str(errormessage))
            res = None
            continue
        if not isvalid(res):
            print(str(errormessage))
            res = None
    return res

def promptPassword(type, message, errormessage, isvalid):


    pass1 =None
    while pass1 is None:
        pass1 = getpass.getpass(prompt=message)
        pass2 = getpass.getpass(prompt="Confirm Password =")
        if pass1 == "" or pass1 != pass2:
            print(str(errormessage))
            pass1=None
            continue
        else:
            if not isvalid(pass1):
                pass1 = None
            else:
                return pass1

def _decode_list(data):
    rv = []
    for item in data:
        if isinstance(item, list):
            item = _decode_list(item)
        elif isinstance(item, dict):
            item = _decode_dict(item)
        rv.append(item)
    return rv

def _decode_dict(data):
    rv = {}
    for key, value in data.items():

        if isinstance(value, list):
            value = _decode_list(value)
        elif isinstance(value, dict):
            value = _decode_dict(value)
        rv[key] = value

    return rv

def loadConfigData(fileName,logger):
    data = {}
    content = ''
    if not os.path.exists(fileName):
        logger.warning('Missing json file: ' + str(fileName))
        return data

    try:
        with open(fileName) as dataFile:
            content = dataFile.read()
    except Exception as e:
        logger.warning('Exception while reading file: ' + fileName + ', exception: ' + str(e))
        return data
    try:
        data = json.loads(json.dumps(json.loads(content, object_hook=_decode_dict)))
    except ValueError:
        logger.warning('Content does not appear to be properly formed Json. fileName: ' + fileName)

    except Exception as e:
        logger.warning('Exception while decoding json file: ' + fileName + ', exception: ' + str(e))

    return data

def is_json(myjson):
    """
    :param myjson: String to check if it is a json format
    :return: Boolean
    """
    try:
        json_object = json.loads(myjson)
    except ValueError:
        return False
    return True

def killPid(pidFile):
    """
    Remove the PID file on exit. Do not let this fail.
    """
    try:
        os.remove(pidFile)
    except:
        pass

def mutex(pidFile):
    """
    Param: None
    Desc:  Handles the mutex operation for lcmctl process.
    Return: True if PID file already exists. Otherwise False
    """

    # If the PID file does not exist, return to program.
    if not os.path.exists(pidFile):
        pidfile = open(pidFile, 'w+')
        # write actual PID number into PID file. Will help you decide if file is bogus/stale
        pidfile.write(str(os.getpid()))
        pidfile.flush()
        pidfile.close()
        return False
    # else never return
    return True

def logStart(logger, msg):
    """
    Param: None
    Desc:  Prints the messages to indicate the start of a particular operation.
    Return: None
    """
    logger.info('##################################################################')
    logger.info('\t' + msg)
    logger.info('##################################################################')

def evacuate(pidFile, code):
    """
    Common exit point to clean up the PID file on exit.
    """
    killPid(pidFile)
    sys.exit(code)

