import json
import time
import platform
import psutil
import requests


def check_os():
    ''' Get operating system you are currently on.
        Returns <True> if you are on Linux-based OS;
        Returns <False> if you are on Win-based OS; '''

    platform_data = platform.uname()
    system = platform_data[0]

    if system == "Windows":
        return False
    elif system == "Linux":
        return True


def lin_daemon():
    ''' Process daemon for Linux-based systems. '''

    initial_processes = [p for p in psutil.process_iter()]
    while True:
        current_processes = [p for p in psutil.process_iter()]
        if len(current_processes) > len(initial_processes):
            for i in current_processes:
                if i not in initial_processes:
                    return (i.name(), i.ppid())
            break
        else:
            continue


def win_daemon():
    ''' Process daemon for Windows-based systems. '''

    import wmi

    watcher = wmi.WMI()
    process_watcher = watcher.Win32_Process.watch_for("creation")
    print("Waiting for process to appear.")
    while True:
        try:
            new_process = process_watcher()
            if new_process.Caption == "tasklist.exe":
                continue
            else:
                process_name = new_process.Caption
                return process_name
        except KeyboardInterrupt:
            break


def get_pid(pname):
    ''' Get process ID(PID) by it's name(pname). '''

    for process in psutil.process_iter():
        if process.name() == pname:
            process_id = process.ppid()
    return process_id


def memory_usage(pid):
    ''' Get process memory consumption in megabytes. '''

    process = psutil.Process(pid=pid)
    memory = process.memory_full_info()[0] / float(2 ** 20)
    return memory


def cpu_usage(pid):
    ''' Get process CPU usage in % per 0.1 seconds. '''

    cpu_load = list()
    for i in range(10):
        process = psutil.Process(pid=pid)
        p_cpu = process.cpu_percent(interval=0.1)
        cpu_load.append(p_cpu)
    return float(sum(cpu_load)) / len(cpu_load)


def send_data(pname, pid, res_time, cpu, mem):
    ''' Send collected data to the remote server. '''

    url = "https://bench-jonsnow123kappa.c9users.io/apply_results"
    data = {"pname": pname, "pid": pid, "time": res_time,
            "cpu": cpu, "mem": mem}
    headers = {"Content-type": "application/json"}

    while True:
        req = requests.post(url, data=json.dumps(data), headers=headers)
        if req.status_code == 200:
            print("Your stats has been applied.")
            break
        else:
            print("Could not submit results, server is not available.")
            time.sleep(5)
            continue


def main():
    ''' Main function. '''

    memory_data = list()
    cpu_data = list()

    while True:
        confirm = input("Do you want to enter data manually?(Y/n)")

        if confirm.lower() == "y":

            p_name = input("Enter process name: ")
            p_id = int(input("Enter process ID: "))
            total_time = int(input("Enter time alive: "))
            try:
                send_data(pname=p_name, pid=p_id, res_time=total_time,
                          cpu="Unrecoreded", mem="Unrecorded")
            except KeyboardInterrupt:
                print("Keyboard interrupt has been used.")
            else:
                confirm_restart = input("Do you want to record more data?(Y/n)")
                if confirm_restart.lower() == "y":
                    continue
                elif confirm_restart.lower() == "n":
                    print("Exitting...")
                    break
                else:
                    print("Unknown input. Exitting...")
                    break
        elif confirm.lower() == "n":

            if check_os():
                process_data = lin_daemon()
                p_name = process_data[0]
                p_id = get_pid(p_name)
            else:
                p_name = win_daemon()
                p_id = get_pid(p_name)

            print(p_name)
            print(p_id)

            time_start = time.time()

            while True:
                try:
                    if (p_name in [p.name() for p in psutil.process_iter()]):
                        memory_data.append(memory_usage(p_id))
                        cpu_data.append(cpu_usage(p_id))
                        print("Data has been recorded.")
                        continue
                    else:
                        print("Process has been terminated.")
                        break
                except psutil.NoSuchProcess:
                    print("Process has been terminated.")
                    break
                except KeyboardInterrupt:
                    print("You have used keyboard interrupt.")
                    break

            time_stop = time.time()

            result_time = time_stop - time_start
            memory_data = sum(memory_data) / len(memory_data)
            cpu_data = sum(cpu_data) / len(cpu_data)

            try:
                send_data(pname=p_name, pid=p_id,
                          res_time=result_time, cpu=cpu_data,
                          mem=memory_data)
            except KeyboardInterrupt:
                print("Keyboard interrupt detected. Exitting...")
            else:
                confirm_restart = input("Do you want to record more data?(Y/n)")
                if confirm_restart.lower() == "y":
                    continue
                elif confirm_restart.lower() == "n":
                    print("Exitting...")
                    break
                else:
                    print("Unknown input. Exitting...")
                    break
        else:
            print("Unknown input, try again.")
            continue


if __name__ == '__main__':
    main()
