#!/usr/bin/env python3

import json

def is_dd_process(process):
    target = process["applying_for"]
    return target == "dd_u" or target == "dd_nu"

def get_active_process(processlist):
    for process in processlist:
        if process["closed_time"] == None:
            if is_dd_process(process):
                return process
    return None

def find_am_for_process(process):
    for AM in process["ams"]:
        if AM["unassigned_time"] == None:
            return AM
    return None

def get_status(process, AM):
    requirements = process["requirements"]
    # first check, if process is approved
    for requirement in requirements:
        if requirement["type"] == "am_ok":
            if requirement["approved_time"] != None:
                return "Approved"
            else:
                break
    # then check, if it's on hold
    if AM["paused"]:
        return "AM Hold"
    # otherwise status is AM
    return "AM"


def get_processes(filename):
    processes = []
    process = {}
    with open('nm-mock.json', 'r') as f:
        dicti = json.load(f)
        for person in dicti["people"]:
            active_process = get_active_process(person["processes"])
            if active_process == None:
                continue
            AM = find_am_for_process(active_process)
            if AM == None:
                continue
            process["AM"] = AM["am"]
            process["Status"] = get_status(active_process, AM)
            processes.append(process.copy())
    return processes

def finduid(uid, processes):
    for process in processes:
        if process["AM"] == uid:
            return True
    return False

def countstatus(status, uid, processes):
    count = 0;
    for process in processes:
        if process["AM"] == uid and process["Status"] == status:
            count=count+1;
    return count;


processes = get_processes("nm-mock.json")
AMs = []
with open('nm-mock.json', 'r') as f:
    dicti = json.load(f)
    for person in dicti["people"]:
        if person["am"] != None:
            am =  person["am"]
            slots = am["slots"]
            uid = person["ldap_fields"]["uid"].strip()
            if person["status"] == "dd_u":
                dd_status = "U"
            else:
               dd_status = "N"
            if slots > 0 or finduid(uid,processes):
                AM = {}
                AM["uid"] = uid
                AM["slots"] = slots
                AM["dd_status"] = dd_status
                AMs.append(AM)
    AMs = sorted(AMs, key=lambda k: (-k['slots'], k['uid']))
    i = 0
    sum_active_ams = 0 # AMs with at least one slot
    sum_active_u_ams = 0 # uploading AMs with at least one slot
    sum_active_n_ams = 0 # non-uploading AMs with at least one slot
    sum_available_ams = 0 # AMs with remaining slots
    sum_available_u_ams = 0 # uploading AMs with remaining slots
    sum_available_n_ams = 0 # non-uploading AMs with remaining slots
    sum_slots = 0
    sum_n_slots = 0
    sum_u_slots = 0
    available_slots = 0
    available_u_slots = 0
    available_n_slots = 0
    for AM in AMs:
        sum_slots = sum_slots + AM["slots"]
        if AM["slots"] > 0:
            sum_active_ams = sum_active_ams+1
            if AM["dd_status"] == "U":
                sum_active_u_ams = sum_active_u_ams+1
                sum_u_slots = sum_u_slots+AM["slots"]
            else:
                sum_active_n_ams = sum_active_n_ams+1
                sum_n_slots = sum_n_slots+AM["slots"]
        remaining = AM["slots"]
        approved = countstatus("Approved",AM["uid"] ,processes)
        hold = countstatus("AM Hold",AM["uid"] ,processes)
        status_am = countstatus("AM",AM["uid"] ,processes)
        remaining = remaining - status_am
        if remaining > 0:
            sum_available_ams = sum_available_ams+1
            if AM["dd_status"] == "U":
                sum_available_u_ams = sum_available_u_ams+1
                available_u_slots = available_u_slots+remaining
            else:
                sum_available_n_ams = sum_available_n_ams+1
                available_n_slots = available_n_slots+remaining
        if remaining < 0:
            remaining = 0
        available_slots = available_slots + remaining
        AM["approved"] = approved
        AM["hold"] = hold
        AM["am"] = status_am
        AM["remaining"] = remaining
        AMs[i] = AM
        i = i + 1
    j = 0
    for AM in AMs:
        am_str = ""
        for i in range (0,AM["am"]):
            am_str = am_str+" x"
        am_str = am_str.strip()
        hold_str = ""
        for i in range (0,AM["hold"]):
            hold_str = hold_str+" h"
        if len(am_str) == 0:
            hold_str = hold_str.strip()
        approved_str = ""
        for i in range (0,AM["approved"]):
            approved_str = approved_str+" a"
        if len(am_str) == 0 and len(hold_str) == 0:
            approved_str = approved_str.strip()
        AM["symbolstr"] = am_str+hold_str+approved_str
        AMs[j] = AM
        j = j+1
    # technically we would also need to check maxlen for slots and remaining -
    # once we'll get the first AM with >= 10 slots, I'm gonna fix the code :)
    maxlen_uid = 0
    maxlen_symbolstr = 0
    for AM in AMs:
        if len(AM["uid"]) > maxlen_uid:
            maxlen_uid = len(AM["uid"])
        if len(AM["symbolstr"]) > maxlen_symbolstr:
            maxlen_symbolstr = len(AM["symbolstr"])
    for AM in AMs:
        print(AM["uid"].rjust(maxlen_uid)+" - "+str(AM["slots"])+\
" "+AM["symbolstr"].ljust(maxlen_symbolstr)+" - "+str(AM["remaining"])+" "+str(AM["dd_status"]))
    print("----------")
    print("sum of slots: "+str(sum_slots)+" ("+str(sum_u_slots)+" U, "+str(sum_n_slots)+\
" N) "+" from "+str(sum_active_ams)+" AMs"+\
" ("+str(sum_active_u_ams)+" U, "+str(sum_active_n_ams)+" N)"+"\n")
    maxlen_uid = 0
    maxlen_symbolstr = 0
    for AM in AMs:
        if AM["remaining"] > 0:
            if len(AM["uid"]) > maxlen_uid:
                maxlen_uid = len(AM["uid"])
            if len(AM["symbolstr"]) > maxlen_symbolstr:
                maxlen_symbolstr = len(AM["symbolstr"])
    for AM in AMs:
        if AM["remaining"] > 0:
            print(AM["uid"].rjust(maxlen_uid)+" - "+str(AM["slots"])+\
" "+AM["symbolstr"].ljust(maxlen_symbolstr)+" - "+str(AM["remaining"])+" "+str(AM["dd_status"]))
    print("----------")
    print("available slots: "+str(available_slots)+\
" ("+str(available_u_slots)+" U, "+str(available_n_slots)+" N) "+" from "+str(sum_available_ams)+" AMs"+\
" ("+str(sum_available_u_ams)+" U, "+str(sum_available_n_ams)+" N)")

