#! /usr/bin/python
#
# D3 -> MonkeyGTD migration.
# Steps done by this script:
#   -> realm 'Work' or 'Personal' as part of tags
#   gtd.project='foo bar' -> tags='[[foo bar]]'
#   gtd.contect='@waiting' -> tags='[[Waiting For]]'
#   gtd.context='foo bar' -> tags=[[foo bar]]'
#   action[-archive] -> Action [Next]
#   project[-archive] -> Project [Active]
#   context -> Context
#   done -> Done
#   reference -> Reference
#
# Usage:
# - check the CUSTOMIZE parts of the script
# - d3tomgtd.py <d3.html >body.html
# - review body.html
# - import after <div id="storeArea">
# - in browser:
#   - Review/Mismatched Realms
#   - turn actions with reminders into ticklers
#   - "Work/Next & Waiting Actions" -> assign person and context to waiting actions


import sys
import re
import xml
import xml.dom
import xml.dom.NodeFilter
import xml.dom.minidom

# parse the document
doc = xml.dom.minidom.parse(sys.stdin)

# D3 project task lists
listentry = re.compile(r'''<<gtdAction.*?>> *\n?|^\.\..+\|.+\n?''', re.MULTILINE)

for div in doc.getElementsByTagName("div"):
    # figure out whether the element is a tiddler based on tags
    isTiddler = False
    tags = div.getAttribute('tags').split()
    for tag in tags:
        if tag in ['action', 'action-archive', 'project', 'project-archive' 'reference', 'context']:
            isTiddler = True
            break

    if isTiddler:
        newtags = []
        isWork = False
        isAction = False
        isProject = False

        # rename tags (capitalize), check whether we have an action tiddler
        for tag in tags:
            if tag in ('action', 'action-archive', 'project', 'project-archive', 'context', 'done'):
                active = True
                if tag.endswith('-archive'):
                    active = False
                    tag = tag.replace('-archive', '')

                if tag == 'action':
                    isAction = True
                elif tag == 'project':
                    isProject = True
                    if active:
                        newtags.append('Active')
                chars = list(tag)
                tag = ''.join([chars[0].upper()] + chars[1:])
                newtags.append(tag)
            elif tag in ('someday', 'unfiled'):
                # CUSTOMIZE: ignore tags which have no further meaning in MonkeyGTD
                pass
            else:
                # preserve tag unchanged
                newtags.append(tag)

        # modify a clone of the current tiddler
        clone = div.cloneNode(True)

        # convert information from special attributes into tags
        for gtdtag in ('gtd.context', 'gtd.project'):
            attr = clone.getAttribute(gtdtag)
            if attr:
                clone.removeAttribute(gtdtag)
                if gtdtag == 'gtd.context' and attr == '@waiting':
                   newtags.append('[[Waiting For]]')
                elif ' ' in attr:
                    newtags.append("[[%s]]" % attr)
                else:
                    newtags.append(attr)
                # set realm based on context
                if gtdtag == 'gtd.context' and attr in '@work':
                    isWork = True

        # actions require a realm to be displayed
        # and one of 'Done', 'Next', '[[Waiting For]]'
        if isAction:
            # CUSTOMIZE: actions are in the 'Work' realm if they are done in the context @work
            if isWork:
                newtags.append('Work')
            else:
                newtags.append('Personal')
            if not 'Done' in newtags and \
                    not '[[Waiting For]]' in newtags:
                newtags.append('Next')
        elif isProject:
            # CUSTOMIZE: all projects are personal by default
            newtags.append('Personal')

        # remove obsolete attributes
        if clone.hasAttribute('gtd.projectindex'):
            clone.removeAttribute('gtd.projectindex')

        # set modified tags
        clone.setAttribute('tags', ' '.join(newtags))

        # clean up tiddler text
        for child in clone.childNodes:
            if child.nodeType == child.TEXT_NODE:
                data = child.data
                # CUSTOMIZE: strip task timer footer (didn't use it in the end)
                data = data.replace(r'''----
|//Description//|//Date//|//Started//|//Stopped//|//Elapsed//|
|/%tasktimer%/|||||
|total||||<<columncalc sum 1 -1>>|''', '')
                # strip D3 action lists from body
                data = listentry.sub('', data)
                data = data.strip()
                child.data = data

        print clone.toxml("utf-8")

