import wx, re, locale
from tiddlywiki import TiddlyWiki
import tweeregex
import metrics

class StatisticsDialog(wx.Dialog):
   """
   A StatisticsDialog displays the number of characters, words,
   passages, links, and broken links in a StoryPanel.

   This is not a live count.
   """

   def __init__(self, parent, storyPanel, app, id = wx.ID_ANY):
       wx.Dialog.__init__(self, parent, id, title = 'Story Statistics')
       self.storyPanel = storyPanel

       # layout

       panel = wx.Panel(parent = self)
       self.panelSizer = wx.BoxSizer(wx.VERTICAL)
       panel.SetSizer(self.panelSizer)

       # count controls

       countPanel = wx.Panel(parent = panel)
       countPanelSizer = wx.FlexGridSizer(6, 2, metrics.size('relatedControls'), metrics.size('relatedControls'))
       countPanel.SetSizer(countPanelSizer)

       self.characters = wx.StaticText(countPanel)
       countPanelSizer.Add(self.characters, flag = wx.ALIGN_RIGHT)
       countPanelSizer.Add(wx.StaticText(countPanel, label = 'Characters'))

       self.words = wx.StaticText(countPanel)
       countPanelSizer.Add(self.words, flag = wx.ALIGN_RIGHT)
       countPanelSizer.Add(wx.StaticText(countPanel, label = 'Words'))

       self.passages = wx.StaticText(countPanel)
       countPanelSizer.Add(self.passages, flag = wx.ALIGN_RIGHT)
       countPanelSizer.Add(wx.StaticText(countPanel, label = 'Passages'))

       self.links = wx.StaticText(countPanel)
       countPanelSizer.Add(self.links, flag = wx.ALIGN_RIGHT)
       countPanelSizer.Add(wx.StaticText(countPanel, label = 'Links'))

       self.brokenLinks = wx.StaticText(countPanel)
       countPanelSizer.Add(self.brokenLinks, flag = wx.ALIGN_RIGHT)
       countPanelSizer.Add(wx.StaticText(countPanel, label = 'Broken Links'))

       self.variablesCount = wx.StaticText(countPanel)
       countPanelSizer.Add(self.variablesCount, flag = wx.ALIGN_RIGHT)
       countPanelSizer.Add(wx.StaticText(countPanel, label = 'Variables Used'))

       self.panelSizer.Add(countPanel, flag = wx.ALL | wx.ALIGN_CENTER, border = metrics.size('relatedControls'))

       self.count(panel)

       okButton = wx.Button(parent = panel, label = 'OK')
       okButton.Bind(wx.EVT_BUTTON, lambda e: self.Close())
       self.panelSizer.Add(okButton, flag = wx.ALL | wx.ALIGN_CENTER, border = metrics.size('relatedControls'))

       self.panelSizer.Fit(self)

       size = self.GetSize()
       if size.width < StatisticsDialog.MIN_WIDTH:
           size.width = StatisticsDialog.MIN_WIDTH
           self.SetSize(size)

       self.panelSizer.Layout()
       self.SetIcon(app.icon)
       self.Show()

   def count(self, panel):
       """
       Sets values for the various counts.
       """

       # have to do some trickery here because Python doesn't do
       # closures the way JavaScript does

       counts = { 'words': 0, 'chars': 0, 'passages': 0, 'links': 0, 'brokenLinks': 0 }
       variables = set()
       tags = set()

       def count(widget, counts):
           if widget.passage.isStoryText():
               counts['chars'] += len(widget.passage.text)
               counts['words'] += len(widget.passage.text.split(None))
               counts['passages'] += 1
               counts['links'] += len(widget.passage.links)
               counts['brokenLinks'] += len(widget.getBrokenLinks())
               # Find variables
               iterator = re.finditer(tweeregex.MACRO_REGEX + "|" + tweeregex.LINK_REGEX, widget.passage.text, re.U|re.I)
               for p in iterator:
                   iterator2 = re.finditer(tweeregex.MACRO_PARAMS_REGEX, p.group(0), re.U|re.I)
                   for p2 in iterator2:
                       if p2.group(4):
                           variables.add(p2.group(4))
               # Find tags
               for a in widget.passage.tags:
                   if a not in TiddlyWiki.INFO_TAGS:
                       tags.add(a)

       self.storyPanel.eachWidget(lambda w: count(w, counts))
       for key in counts:
           counts[key] = locale.format('%d', counts[key], grouping = True)

       self.characters.SetLabel(str(counts['chars']))
       self.words.SetLabel(str(counts['words']))
       self.passages.SetLabel(str(counts['passages']))
       self.links.SetLabel(str(counts['links']))
       self.brokenLinks.SetLabel(str(counts['brokenLinks']))
       self.variablesCount.SetLabel(str(len(variables)))

       if len(variables):
           text = ', '.join(sorted(variables))
           variablesCtrl = wx.TextCtrl(panel, -1, size=(StatisticsDialog.MIN_WIDTH*.9, 60), style=wx.TE_MULTILINE|wx.TE_READONLY)
           variablesCtrl.AppendText(text)
           self.panelSizer.Add(variablesCtrl, flag = wx.ALIGN_CENTER)

       if len(tags):
           text = ', '.join(sorted(tags))
           tagsCtrl = wx.TextCtrl(panel, -1, size=(StatisticsDialog.MIN_WIDTH*.9, 60), style=wx.TE_MULTILINE|wx.TE_READONLY)
           tagsCtrl.AppendText(text)
           self.panelSizer.Add(wx.StaticText(panel, label = str(len(tags)) + " Tags"), flag = wx.ALIGN_CENTER)
           self.panelSizer.Add(tagsCtrl, flag = wx.ALIGN_CENTER)

   MIN_WIDTH = 300