import random
import datetime


class RandomDatetime(object):

    def __init__(self, pre_days=30, post_days=30):
        self.pre_days = pre_days
        self.post_days = post_days
        self.now = datetime.datetime.now()

    def datetime(self, pre=None, post=None):
        pre = self.pre_days if pre is None else pre
        post = self.post_days if post is None else post
        delta = datetime.timedelta(random.randrange(- pre, post + 1))
        return self.now + delta

    def date(self, **kwds):
        return datetime.date(*self.datetime(**kwds).timetuple()[:3])


def timedeltastr(timedelta):
    hour = timedelta.seconds // 60 // 60
    min = timedelta.seconds // 60 - (hour * 60)
    return '{0:02d}:{1:02d}'.format(timedelta.days * 24 + hour, min)


def node(level, heading, todo=None, scheduled=None, deadline=None,
         closed=None, clock=[]):
    active_datestr = lambda x: x.strftime('<%Y-%m-%d %a>')
    inactive_datestr = lambda x: x.strftime('[%Y-%m-%d %a]')
    inactive_datetimestr = lambda x: x.strftime('[%Y-%m-%d %a %H:%M]')
    yield '*' * level
    yield ' '
    if todo:
        yield todo
        yield ' '
    yield heading
    yield '\n'
    if scheduled or deadline or closed:
        yield ' ' * level
    for (name, date, datestr) in [('CLOSED', closed, inactive_datestr),
                                  ('DEADLINE', deadline, active_datestr),
                                  ('SCHEDULED', scheduled, active_datestr)]:
        if date:
            yield ' '
            yield name
            yield ': '
            yield datestr(date)
    if scheduled or deadline or closed:
        yield '\n'
    for (clock_start, clock_end) in clock:
        yield ' ' * (level + 1)
        yield 'CLOCK: '
        yield inactive_datetimestr(clock_start)
        yield '--'
        yield inactive_datetimestr(clock_end)
        yield ' => '
        yield timedeltastr(clock_end - clock_start)
        yield '\n'


def makeorg(num, **kwds):
    heading_pops = ['aaa', 'bbb', 'ccc']
    true_or_false = [True, False]
    rd = RandomDatetime(**kwds)
    for i in range(num):
        kwds = {}
        if i == 0:
            kwds['level'] = 1
        else:
            kwds['level'] = random.randrange(1, 4)
        kwds['heading'] = random.choice(heading_pops)
        if random.choice(true_or_false):
            if random.choice(true_or_false):
                kwds['todo'] = 'TODO'
            else:
                kwds['closed'] = rd.date(post=0)
                kwds['todo'] = 'DONE'
        for sdc in ['scheduled', 'deadline']:
            if random.choice(true_or_false):
                kwds[sdc] = rd.date()
        if random.choice(true_or_false):
            kwds['clock'] = clock = []
            for _ in range(random.randrange(1, 5)):
                start = rd.datetime(post=0)
                end = start + datetime.timedelta(
                    0, random.randrange(1, 5) * 60 * 60)
                clock.append((start, end))
        for s in node(**kwds):
            yield s


def writeorg(file, *args, **kwds):
    file.writelines(makeorg(*args, **kwds))


def run(num):
    import sys
    writeorg(sys.stdout, num)

@@ -860,19 +860,28 @@
 clock=%5B%5D
+, tags=%5B%5D
 ):%0A
-
     acti
@@ -1167,16 +1167,76 @@
 heading%0A
+    if tags:%0A        yield '  :%7B0%7D:'.format(':'.join(tags))%0A
     yiel
@@ -2080,16 +2080,86 @@
  'ccc'%5D%0A
+    tags_pops = %5B'work', 'boss', 'notes', 'action', '@home', '@work'%5D%0A
     true
@@ -3064,24 +3064,24 @@
  * 60 * 60)%0A
-
             
@@ -3111,16 +3111,111 @@
 , end))%0A
+        if random.choice(true_or_false):%0A            kwds%5B'tags'%5D = %5Brandom.choice(tags_pops)%5D%0A
         

Generate tags in orgviz.randomnodes