#!/usr/bin/env python

"""tasksscraper.outlook: ...."""

__author__ = "Daniel Engvall"
__email__ = "daniel@engvalls.eu"

import osascript
from typing import List
import json
from loguru import logger
import re


def remove_invalid_brackets(dirty_json):
    """Sanitize JSON from extra brackets caused by AppleScript

    Args:
        dirty_json:

    Returns: String without extra brackets

    """
    output_data = dirty_json.replace('\n', '')
    re_rules = [(r'(?s),[\{]{2,}', r',{')]
    current_count = 1
    max_count = 100  # TODO: a nasty workaround for weird behavior found using Python 3.8
    all_ok = False
    while not all_ok and current_count <= max_count:
        for replace_match, replace_with in re_rules:
            output_data = re.sub(replace_match, replace_with, output_data, re.DOTALL)
        all_ok = all([re.match(r, output_data) for r, _ in re_rules])
        current_count += 1
    output_data = output_data.replace('{{{', '{')
    return output_data


def fix_quotes_json_strings(dirty_json):
    """Replace double-quotes with JSON strings causing issues

    Args:
        dirty_json:

    Returns: Returns a string without invalid quotes

    """
    output_data = dirty_json
    all_tasks = re.findall(r'"taskName":"(.+?)","', dirty_json)
    fix_tasks = [(t, t.replace('"', "'")) for t in all_tasks if '"' in t]
    print(fix_tasks)
    for fix_from, fix_to in fix_tasks:
        print(f'{fix_from} {fix_to}')
        output_data = output_data.replace(fix_from, fix_to)
    return output_data


def get_outlook_tasks() -> List:
    """Get Outlook tasks

    Returns:
        List of tasks from Outlook

    """
    # noinspection PyPep8,PyPep8
    c, o, e = osascript.run('''
    -- display dialog "Will now process all current outlook tasks selected"
    tell application "Microsoft Outlook"
        -- activate
        set x to ""
        set selectedTasks to selected objects
        if selectedTasks is {} then
            display dialog "Please select a task first and then run this script." with icon 1
            return
        end if
        repeat with theTask in selectedTasks
            set c to "{"
            if class of theTask is task then
                set c to c & "\\"taskName\\":\\"" & name of theTask & "\\""
                set theContent to plain text content of theTask
                if theContent is missing value then
                    set theContent to ""
                end if
                set c to c & ",\\"taskContent\\":\\"" & "none" & "\\""
                set theFolder to folder of theTask
                set c to c & ",\\"taskFolder\\":\\"" & name of theFolder & "\\""
                set c to c & ",\\"modifiedDate\\":\\"" & modification date of theTask & "\\""
                set c to c & ",\\"startDate\\":\\"" & start date of theTask & "\\""
                set c to c & ",\\"due\\":\\"" & due date of theTask & "\\""
                set c to c & ",\\"completeDate\\":\\"" & completed date of theTask & "\\""
                set c to c & ",\\"taskPriority\\":\\"" & priority of theTask & "\\""
                set theCategory to category of theTask
                set catList to "["
                set cat_count to 0 as number
                repeat with oneCat in theCategory
                    if oneCat is not equal to ""
                        set theCategoryName to name of oneCat
                        if cat_count > 0 then
                            set catList to (catList & ",") as string
                        end if
                        set catList to catList & "\\"" & theCategoryName & "\\""
                        set cat_count to cat_count + 1 as number
                    end if
                end repeat
                set catList to catList & "]"
                set c to c & ",\\"taskCategories\\":" & catList
                set c to c & "},"
            end if
        set x to (x & c) as string
        end repeat
    end tell
    return x
    ''') # nopep8
    o = o.strip(',')
    o = f'[{o}]'
    logger.info(f'osascript error: {e}')
    logger.info(f'osascript output: {o}')
    logger.info(f'sanitizing JSON generated by AppleScript')
    logger.debug(f'result after sanitizing {o}')
    o = remove_invalid_brackets(o)
    o = fix_quotes_json_strings(o)
    if len(o) <= 10:
        logger.warning('less than 10 characters from Outlook, probably nothing there. Skipping Outlook')
    if c == 0:
        try:
            result = json.loads(o)
        except json.decoder.JSONDecodeError:
            logger.opt(exception=True).error('unable to parse JSON from Outlook - skipping Outlook, see the body printed')
            print(o)
            return None
        return result
    else:
        return None