#!/usr/bin/env python
# coding: utf-8
# v0.3 - 24/02/2020

# Copyright (C) 2019:
#     Linexos Team, technique@linexos.com

from posixpath import split
import time
import os
import sys
from datetime import datetime, timedelta
import re
import argparse
from argparse import RawTextHelpFormatter
import textwrap
import base64
import subprocess
import os.path
from os import path

# Code de retour standard
RC_STATUS = ''
RC_NUM = 0
RC_OK = 0
RC_WARNING = 1
RC_CRITICAL = 2
RC_UNKNOWN = 3


# Box HTML [ok][warning][critical][unknown]
ok_html = "<span style=' top: 5px; border: 1px solid green; border-radius: 5px; box-shadow: 1px 1px 1px grey; color: green; background-color: #DDF1D5; font-weight: bold; padding: 1px 7px; margin-right :5px; font-size: 12px; font-family: Lato,Helvetica,Arial,sans-serif;'> OK </span>"
infos_html = "<span style=' top: 5px; border: 1px solid green; border-radius: 5px; box-shadow: 1px 1px 1px grey; color: green; background-color: #f2f2f2; font-weight: bold; padding: 1px 7px; margin-right :5px; font-size: 12px; font-family: Lato,Helvetica,Arial,sans-serif;'> INFOS </span>"
unknown_html = "<span style=' top: 5px; border: 1px solid grey; border-radius: 5px; box-shadow: 1px 1px 1px grey; color: grey; background-color: #f2f2f2; font-weight: bold; padding: 1px 7px; margin-right :5px; font-size: 12px; font-family: Lato,Helvetica,Arial,sans-serif;'> UNKNOWN </span>"
warning_html = "<span style=' top: 5px; border: 1px solid orange; border-radius: 5px; box-shadow: 1px 1px 1px grey; color: orange; background-color: #F1DCA9; font-weight: bold; padding: 1px 7px; margin-right :5px; font-size: 12px; font-family: Lato,Helvetica,Arial,sans-serif;'> WARNING </span>"
critical_html = "<span style=' top: 5px; border: 1px solid red; border-radius: 5px; box-shadow: 1px 1px 1px grey; color: red; background-color: #F7BEBB; font-weight: bold; padding: 1px 7px;margin-top: 2px; margin-right :5px; font-size: 12px; font-family: Lato,Helvetica,Arial,sans-serif;'> CRITICAL </span>"


# Argument wrapper
class PreserveWhiteSpaceWrapRawTextHelpFormatter(argparse.RawDescriptionHelpFormatter):
    def __add_whitespace(self, idx, iWSpace, text):
        if idx is 0:
            return text
        return (" " * iWSpace) + text

    def _split_lines(self, text, width):
        textRows = text.splitlines()
        for idx,line in enumerate(textRows):
            search = re.search('\s*[0-9\-]{0,}\.?\s*', line)
            if line.strip() is "":
                textRows[idx] = " "
            elif search:
                lWSpace = search.end()
                lines = [self.__add_whitespace(i,lWSpace,x) for i,x in enumerate(textwrap.wrap(line, width))]
                textRows[idx] = lines

        return [item for sublist in textRows for item in sublist]


parser = argparse.ArgumentParser(
    prog='CHECK-SYNC-CASHDESK',
    add_help=True,
    formatter_class=PreserveWhiteSpaceWrapRawTextHelpFormatter,
    description=textwrap.dedent(" "),
    epilog=textwrap.dedent(" "))


parser.add_argument("-b", "--bash",
                    metavar="BASH",
                    help="The path to use",
                    required=True)

parser.add_argument("-s", "--space",
                    metavar="SPACE",
                    help="The space to check",
                    required=True)

parser.add_argument("-t", "--timeout",
                    metavar="TIMEOUT",
                    help="The timeout",
                    required=True)

parser.add_argument("-w", "--warning",
                    metavar="WARNING",
                    help="The warning",
                    required=True)

parser.add_argument("-c", "--critical",
                    metavar="CRITICAL",
                    help="The critical",
                    required=True)

try:
    args = parser.parse_args()
except:
    parser.exit(RC_UNKNOWN)


if not args.bash:
    print(unknown_html+" Missing bash parameter. Use [-p] or [--path] to do it.")
    sys.exit(RC_UNKNOWN)

if not args.space:
    print(unknown_html+" Missing space parameter (g1heap,edenspace,G1OldGeneration or all). Use [-s] or [--space] to do it.")
    sys.exit(RC_UNKNOWN)


if not args.timeout:
    print(unknown_html+" Missing timeout parameter. Use [-t] or [--timeout] to do it.")
    sys.exit(RC_UNKNOWN)

if not args.warning:
    print(unknown_html+" Missing warning parameter. Use [-w] or [--warning] to do it.")
    sys.exit(RC_UNKNOWN)

if not args.critical:
    print(unknown_html+" Missing critical parameter. Use [-c] or [--critical] to do it.")
    sys.exit(RC_UNKNOWN)

###Variables###

#Variable

#Liste
t1 = []
t2 = []
t3 = []
t4 = []
id = []

###Analyse JPS###

#Assemblage de la commande
#test = "whoami"
#test2 = os.popen(test).read()
#sys.path.insert(0, "/usr/local/bin:/usr/bin:/bin")


getid = "jps -v | grep " + args.bash + "| awk '{ print $1 }'"
#Execution
idjvm = os.popen(getid).read()
id = idjvm.split('\n')

if len(id[0]) > 0:
    getmap = "jmap -heap " + id[0]
else:
    #print(ok_html + "cette jvm n'est pas en cours de fonctionnement")
    print("%s  cette jvm n'est pas en cours de fonctionnement"% (ok_html))
    exit(0)

#Execution
jmap = os.popen(getmap).read()
t2.append(jmap)

liste = t2[0].split("\n")
dico = {}
sous_dico = {}
sous_sous_dico = {}
sous_sous_sous_dico = {}
master_key = None
slave_key = None
sub_key = None

for e in liste[9:]:
    line = list(x for x in e.split('='))
    #print("line", line)
    if line == ['']:
        if master_key is not None:
            master_key = None
            slave_key = None
            sub_key = None
        elif slave_key is not None:
            slave_key = None
            sub_key = None
        elif sub_key is not None:
            sub_key = None
    elif ':' in line[0]:
        if master_key is None:
            master_key = line[0].replace(':', '')
            #print("\t\t\tmaster_key", master_key)
            if master_key not in dico.keys():
                dico.update({master_key: {}})
        elif slave_key is None:
            slave_key = line[0].replace(':', '').replace(" ", "")
            #print("\t\t\tslave_key", slave_key)
            if slave_key not in dico[master_key].keys():
                dico[master_key].update({slave_key: {}})

        else:
            sub_key = line[0].replace(':', '').replace(" ", "")
             #print("\t\t\tsub_key", sub_key)
            if sub_key not in dico[master_key][slave_key].keys():
                dico[master_key][slave_key].update({sub_key: {}})

    else:
        if master_key and slave_key and sub_key:
            if len(line) == 2:
                if '(' in line[1]:
                    sub_split = line[1].split('(')
                    dico[master_key][slave_key][sub_key][line[0].replace(" ", "")] = [sub_split[0].replace(" ", ""), sub_split[1].replace(")","")]
                else:
                    dico[master_key][slave_key][sub_key][line[0].replace(" ", "")] = line[1]

            elif '%' in line[0]:
                dico[master_key][slave_key][sub_key]["used"] = line[0].replace("used","").replace(" ","")
                sub_key = None
        elif master_key and slave_key:
            if len(line) == 2:
                if '(' in line[1]:
                    sub_split = line[1].split('(')
                    dico[master_key][slave_key][line[0].replace(" ", "")] = [sub_split[0].replace(" ", ""), sub_split[1].replace(")","")]
                else:
                    dico[master_key][slave_key][line[0].replace(" ", "")] = line[1]
            elif '%' in line[0]:
                dico[master_key][slave_key]["used"] = line[0].replace("used","").replace(" ","")
                slave_key = None

        elif master_key:
            if len(line) == 2:
                if '(' in line[1]:
                    sub_split = line[1].split('(')
                    dico[master_key][line[0].replace(" ", "")] = [sub_split[0].replace(" ", ""), sub_split[1].replace(")","")]
                else:
                    dico[master_key][line[0].replace(" ", "")] = line[1]
            elif '%' in line[0]:
                dico[master_key]["used"] = line[0].replace("used","").replace(" ","")
                master_key = None


###Analyse JVM###


if args.space == "edenspace":
    heapeden = dico["Heap Usage"]["EdenSpace"]["used"]

    if heapeden > args.warning and heapeden < args.critical:
        #print warning_html, 'edenspace is warning', heapeden
        print ("%s edenspace is warning %s | edenspace=%s;%s;%s;0;100" % (warning_html,heapeden,heapeden,args.warning,args.critical))
        exit(1)
    elif heapeden > args.critical:
        #print critical_html, 'edenspace is critical', heapeden
        print ("%s edenspace is critical %s | edenspace=%s;%s;%s;0;100" % (critical_html,heapeden,heapeden,args.warning,args.critical))
        exit(2)
    else:
        # print ok_html, 'edenspace is ok', heapeden, 'edenspace=', heapeden;args.warning;args.critical;0;100
        print ("%s edenspace is ok %s | edenspace=%s;%s;%s;0;100" % (ok_html,heapeden,heapeden,args.warning,args.critical))
        # print ("%s edenspace is ok %s | edenspace=%s;%s;%s;0;100 | JVMs is : %s -- UID is : %s" % (ok_html,heapeden,heapeden,args.warning,args.critical,idjvm,uid))
        exit(0)

elif args.space == "fromspace":
    heapg1heap = dico["Heap Usage"]["FromSpace"]["used"]

    if heapg1heap > args.warning and heapg1heap < args.critical:
        #print warning_html, 'g1heap is warning', heapg1heap
        print ("%s fromspace is warning %s | fromspace=%s;%s;%s;0;100" % (warning_html,heapg1heap,heapg1heap,args.warning,args.critical))
        exit(1)
    if heapg1heap > args.critical:
        #print critical_html, 'g1heap is critical', heapg1heap
        print ("%s fromspace is critical %s | fromspace=%s;%s;%s;0;100" % (critical_html,heapg1heap,heapg1heap,args.warning,args.critical))
        exit(2)
    else:
        #print ok_html, 'g1heap is ok', heapg1heap
        print ("%s fromspace is ok %s | fromspace=%s;%s;%s;0;100" % (ok_html,heapg1heap,heapg1heap,args.warning,args.critical))
        exit(0)

elif args.space == "tospace":
    heapg1old = dico["Heap Usage"]["ToSpace"]["used"]

    if heapg1old > args.warning and heapg1old < args.critical:
        #print warning_html, 'g1oldGeneration is warning', heapg1old
        print ("%s tospace is warning %s | tospace=%s;%s;%s;0;100" % (warning_html,heapg1old,heapg1old,args.warning,args.critical))
        exit(1)
    if heapg1old > args.critical:
        #print critical_html, 'g1oldGeneration is critical', heapg1old
        print ("%s tospace is critical %s | tospace=%s;%s;%s;0;100" % (critical_html,heapg1old,heapg1old,args.warning,args.critical))
        exit(2)
    else:
        #print ok_html, 'g1oldGeneration is ok', heapg1old
        print ("%s tospace is ok %s | tospace=%s;%s;%s;0;100" % (ok_html,heapg1old,heapg1old,args.warning,args.critical))
        exit(0)

elif args.space == "all":
    heapeden = dico["Heap Usage"]["EdenSpace"]["used"]
    heapg1heap = dico["Heap Usage"]["FromSpace"]["used"]
    heapg1old = dico["Heap Usage"]["ToSpace"]["used"]

    if heapg1old > args.warning and heapg1old < args.critical or heapg1heap > args.warning and heapg1heap < args.critical or heapeden > args.warning and heapeden < args.critical:
        print("%s résultat warning : edenspace is %s fromspace is %s tospace is %s | edenspace=%s;%s;%s;0;100 fromspace=%s;%s;%s;0;100 tospace=%s;%s;%s;0;100" % (warning_html,heapeden,heapg1heap,heapg1old,heapeden,args.warning,args.critical,heapg1heap,args.warning,args.critical,heapg1old,args.warning,args.critical))
        exit(1)
    elif heapg1old > args.critical or heapg1heap > args.critical or heapeden > args.critical:
        print("%s résultat critique : edenspace is %s fromspace is %s tospace is %s | edenspace=%s;%s;%s;0;100 fromspace=%s;%s;%s;0;100 tospace=%s;%s;%s;0;100" % (critical_html,heapeden,heapg1heap,heapg1old,heapeden,args.warning,args.critical,heapg1heap,args.warning,args.critical,heapg1old,args.warning,args.critical))
        exit(2)
    else:
        print("%s résultat ok : edenspace is %s fromspace is %s tospace is %s | edenspace=%s;%s;%s;0;100 fromspace=%s;%s;%s;0;100 tospace=%s;%s;%s;0;100" % (ok_html,heapeden,heapg1heap,heapg1old,heapeden,args.warning,args.critical,heapg1heap,args.warning,args.critical,heapg1old,args.warning,args.critical))
        exit(0)
else:
    print ("%s space inexistant, utiliser un des spaces suivant : edenspace,fromspace,tospace or all" % (unknown_html))
    exit(3)
