#!{{ python_executable }}

import datetime
import json
import os
import subprocess
import sys
import time
from optparse import OptionParser, make_option

instance_path = "{{ directory['home'] }}"
monitor_dir = "{{ directory['monitor'] }}"
pid_dir = "{{ directory['run'] }}"
promise_dir = "{{ directory['promise'] }}"

monitoring_file_json = "{{ monitoring_file_json }}"
monitoring_folder_bool = "{{ monitoring_folder_bool }}"

option_list = [
  make_option("-a", "--all", action="store_true", dest="all",
              help="test everything : promises, services, customs"),
  make_option("-n", "--no-write", action="store_true", dest="only_stdout",
              help="just show the json output on stdout"),
  make_option("-m", "--monitors", action="store_true", dest="monitor",
              help="add the custom monitoring file to the files to monitor"),
  make_option("-p", "--promises", action="store_true", dest="promise",
              help="add the promises\'file to the files to monitor"),
  make_option("-s", "--services", action="store_true", dest="service",
              help="add the file containing services\'pid to the files to monitor")
]


def getListOfScripts(directory):
  scripts = []
  if os.path.exists(directory) and os.path.isdir(directory):
    for file in os.listdir(directory):
      scripts.append(os.path.join(directory, file))
  else:
    exit("There is a problem in your directories" \
          "of monitoring. Please check them")
  return scripts

def runServices(directory):
  services = getListOfScripts(directory)
  result = {}
  for service in services:
    service_path = os.path.join(pid_dir, service)
    service_name = os.path.basename(service_path)
    try:
      pid = int(open(service_path).read())
    ### because apache (or others) can write sockets
    except IOError:
      continue
    try:
      os.kill(pid, 0)
      result[service_name] = ''
    except OSError:
      result[service_name] = "This service is not running anymore"
  return result


def runScripts(directory):
  scripts = getListOfScripts(directory)
  script_timeout = 3
  result = {}
  for script in scripts:
    command = [os.path.join(promise_dir, script)]
    script = os.path.basename(command[0])
    result[script] = ''

    process_handler = subprocess.Popen(command,
                                       cwd=instance_path,
                                       env=None if sys.platform == 'cygwin' else {},
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       stdin=subprocess.PIPE)
    process_handler.stdin.flush()
    process_handler.stdin.close()
    process_handler.stdin = None

    time.sleep(script_timeout)

    if process_handler.poll() is None:
      process_handler.terminate()
      result[script] = "Time Out"
    elif process_handler.poll() != 0:
      stderr = process_handler.communicate()[1]
      if stderr is not None:
        result[script] = stderr.strip()
  return result


def writeFiles(monitors):
  fail = False
  for i in monitors.values():
    if i != "" :
      fail = True
  if fail:
    message = "FAILURE : something went wrong\n"
  else:
    message = "SUCCESS : everything is ok\n"
  date = datetime.datetime.now().ctime()
  monitors['datetime'] = date
  file_bool = os.path.join(monitoring_folder_bool, str(time.time()))
  open(file_bool, "w+").write(date + "," +  message)
  open(monitoring_file_json, "w+").write(json.dumps(monitors))


if __name__ == "__main__":
  parser = OptionParser(option_list=option_list)
  monitors = {}
  (options, args) = parser.parse_args()

  if not (options.monitor or options.promise
         or options.service or options.all):
    exit("Please provide at list one arg in : -a, -m, -p, -s")

  if options.monitor or options.all:
    monitors.update(runScripts(monitor_dir))
  if options.promise or options.all:
    monitors.update(runScripts(promise_dir))
  if options.service or options.all:
    monitors.update(runServices(pid_dir))

  if options.only_stdout:
    print json.dumps(monitors)
  else:
    writeFiles(monitors)
  if len(monitors) == 0:
    exit(0)
  else:
    exit(1)