#!/usr/bin/env python3

import sys
import os
import json
import requests
import argparse
from pprint import pprint
import time

CAMUNDA="http://localhost:8085/engine-rest/"

def get_current_deployments(key = 'sentiment-analysis'):
    res = requests.get(CAMUNDA + "deployment")
    #return [proc for proc in res.json() if proc['name'] == key]
    return res.json()

def get_current_process_instances(key = 'sentiment-analysis'):
    res = requests.get(CAMUNDA + 'process-instance')
    if (key is None):
        return res.json()
    else:
        return [instance for instance in res.json() if instance['definitionId'].startswith(key + ":")]

def cleanup_old_deployments(key='sentiment-analysis'):
    print ("Cleaning up old deployments")
    for deployment in get_current_deployments(key):
        res = requests.delete(CAMUNDA + "deployment/" + deployment['id'] + "?cascade=true&skipCustomListeners=true")
        if (res.status_code == 204):
            print ("Cleaned up deployment {}".format(deployment['id']))
        else:
            print ("Error cleaning old deployment {}: Code: {}".format(deployment['id'], res.status_code))
            try:
                pprint(res.json())
            except:
                pprint(res.content)

def get_users():
    res = requests.get(CAMUNDA + "user")
    return res.json()

def get_groups():
    res = requests.get(CAMUNDA + "group")
    return res.json()

def cleanup_users(keep = ["demo"]):
    for user in get_users():
        # keep user "demo"
        if user['id'] in keep:
            continue

        res = requests.delete(CAMUNDA + "user/" + user['id'])
        if (res.status_code == 204):
            print ("Cleaned up user {}".format(user['id']))
        else:
            print ("Error cleaning user {}: Code: {}".format(user['id'], res.status_code))
            try:
                pprint(res.json())
            except:
                pprint(res.content)

def cleanup_groups():
    for group in get_groups():
        res = requests.delete(CAMUNDA + "group/" + group['id'])
        if (res.status_code == 204):
            print ("Cleaned up group {}".format(group['id']))
        else:
            print ("Error cleaning group {}: Code: {}".format(group['id'], res.status_code))
            try:
                pprint(res.json())
            except:
                pprint(res.content)

def get_authorizations():
    res = requests.get(CAMUNDA + "authorization")
    return res.json()

def create_admin_user():
    # create user
    params = {
            "profile": {
                "id": "admin",
                "firstName": "Admin",
                "lastName": "User",
                "email": "aic@dsg.tuwien.ac.at"
                },
            "credentials": {
                "password": "admin"
                }
            }
    res = requests.post(CAMUNDA + "user/create", json=params)
    if (res.status_code == 204):
        print ("Created user admin")
    else:
        print ("Error creating user admin: Code: {}".format(res.status_code))
        try:
            pprint(res.json())
        except:
            pprint(res.content)


    # clean all authorizations
    for auth in get_authorizations():
        res = requests.delete(CAMUNDA + "authorization/" + auth['id'])
        if (res.status_code == 204):
            print ("Cleaned up authorization {}".format(auth['id']))
        else:
            print ("Error cleaning authorization {}: Code: {}".format(auth['id'], res.status_code))
            try:
                pprint(res.json())
            except:
                pprint(res.content)


    # set all permissions for modifying users
    params = {
            "type": 1,
            "permissions": ["ALL"],
            "userId": "admin",
            "groupId": None,
            "resourceType": 1,
            "resourceId": "admin"
            }
    res = requests.post(CAMUNDA + "authorization/create", json=params)
    if (res.status_code == 200):
        print ("Set users permissions for admin users")
    else:
        print ("Error setting users permissions for admin user: Code: {}".format(res.status_code))
        try:
            pprint(res.json())
        except:
            pprint(res.content)

    # create admin group
    params = {
            "id": "camunda-admin",
            "name": "camunda BPM Administrators",
            "type": "SYSTEM"
            }
    res = requests.post(CAMUNDA + "group/create", json=params)
    if (res.status_code == 204):
        print ("Created user admin")
    else:
        print ("Error creating group camunda-admin: Code: {}".format(res.status_code))
        try:
            pprint(res.json())
        except:
            pprint(res.content)

    # add admin user to camunda-admin
    res = requests.put(CAMUNDA + "group/camunda-admin/members/admin")
    if (res.status_code == 204):
        print ("Added admin to camunda-admin")
    else:
        print ("Error adding user admin to group camunda-admin: Code: {}".format(res.status_code))
        try:
            pprint(res.json())
        except:
            pprint(res.content)

    # set all permissions for admin group
    for resourceType in range(0, 16):
        params = {
                "type": 1,
                "permissions": ["ALL"],
                "userId": None,
                "groupId": "camunda-admin",
                "resourceType": resourceType,
                "resourceId": "*"
                }
        res = requests.post(CAMUNDA + "authorization/create", json=params)
        if (res.status_code == 200):
            print ("Set group permissions for id {}".format(resourceType))
        else:
            print ("Error setting application permissions for admin user: Code: {}".format(res.status_code))
            try:
                pprint(res.json())
            except:
                pprint(res.content)

def get_filters():
    res = requests.get(CAMUNDA + "filter")
    return res.json()

def cleanup_filters(keep = ["All Tasks"]):
    for filter in get_filters():
        # keep filter "All Tasks"
        if filter['name'] in keep:
            continue

        res = requests.delete(CAMUNDA + "filter/" + filter['id'])
        if (res.status_code == 204):
            print ("Cleaned up filter {}".format(filter['name']))
        else:
            print ("Error cleaning filter {} ({}): Code: {}".format(filter['name'], filter['id'], res.status_code))
            try:
                pprint(res.json())
            except:
                pprint(res.content)

def create_deployment(cleanup=False):
    parameters = [
            ("deployment-name", "sentiment-analysis"),
            #("enable-duplicate-filtering", "true"),
            #("deploy-changed-only", "true"),
            ("file1", open("sentiment-analysis.bpmn")),
            ("file2", open("forms/input-terms.html")),
            ("file3", open("forms/download-pdf.html")),
            ]
    if cleanup:
        cleanup_old_deployments()
    res = requests.post(CAMUNDA + "deployment/create", files=parameters)
    if (res.status_code == 200):
        print ("Successfully deployed Sentiment Analysis")
    else:
        pprint ("Status Code: {}".format(res.status_code))
        try:
            pprint(res.json())
        except:
            pprint(res.content)

def submit_terms(terms):
    termlist = [{'term': term} for term in terms]
    # submit to camunda
    params = {
            'variables': {
                'terms': {
                    'value': json.dumps(termlist),
                    'type': "json",
                    'valueInfo': {
                        'serializationDataFormat': "application/json",
                        }
                    }
                }
            }
    res = requests.post(CAMUNDA + "process-definition/key/sentiment-analysis/start", json=params)
    if (res.status_code == 200):
        print ("Successfully started Sentiment Analysis")
    else:
        pprint ("Status Code: {}".format(res.status_code))
        try:
            pprint(res.json())
        except:
            try:
                import xml.dom.minidom
                content = res.content.decode('utf-8').replace('<!doctype html>', '')
                print(xml.dom.minidom.parseString(content).toprettyxml())
            except:
                pprint(res.content)

def download_pdf():
    instances = get_current_process_instances()
    if len(instances) == 0:
        print ("Error: no running instance found.")
        return
    instance = instances[0]['id']
    res = requests.get(CAMUNDA + 'process-instance/' + instance + '/variables')
    try:
        pprint(res.json())
    except:
        pprint(res.content)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--no-deploy', dest='deploy', default=True, action='store_false', help="Do not run the deployment step")
    parser.add_argument('--no-cleanup', dest='cleanup', default=True, action='store_false', help="Initial deploy does not need cleanup")
    parser.add_argument('--autoclick', dest='autoclick', type=int, default=0, help="How many steps to autoclick")
    parser.add_argument('--terms', dest='terms', type=str, nargs='*', default=["aic", "TU Wien"], help="How many steps to autoclick")
    args = parser.parse_args()

    if args.deploy:
        # initialize camunda process
        create_deployment(cleanup=args.cleanup)
        if args.cleanup:
            cleanup_users()
            cleanup_groups()
            cleanup_filters()
            create_admin_user()

    if args.autoclick >= 1:
        # start clicking
        submit_terms(args.terms)

    if args.autoclick >= 2:
        download_pdf()


if __name__ == "__main__":
    loop_main = True
    while loop_main:
        try:
            main()
            loop_main = False
        except KeyboardInterrupt:
            raise
        except:
            print("looks bad - retry in 10 sec - "+str(sys.exc_info()[0]))
            time.sleep(10)
