# This module is part of the Divmod project and is Copyright 2003 Amir Bakhtiar:
# amir@divmod.org.  This is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#

from __future__ import generators
from Tkinter import *
import tkFileDialog
import tkSimpleDialog
import tkMessageBox
import os
import time

class TestView(Frame):
    def __init__(self, parent=None, guesser=None, app=None):
        Frame.__init__(self, parent)
        self.pack()
        self.guesser = guesser
        self.app = app
        self.size = 300
        self.setupViews()
        

    def setupViews(self):
        line = Frame(self, relief=RAISED, borderwidth=1)
        line.pack(side=TOP, padx=2, pady=1)
        colHeadings = [('Guesses', 8), ('Right', 8), ('Wrong', 8), ('Accuracy %', 10)]
        currCol = 0
        for cHdr, width in colHeadings:
            l = Label(line, text=cHdr, width=width, bg='lightblue')
            l.grid(row=0, column=currCol)
            currCol += 1
        line = Frame(self)
        line.pack(fill=X)

        iGuess = IntVar()
        iRight = IntVar()
        iWrong = IntVar()
        iAcc = IntVar()
        self.model = (iGuess, iRight, iWrong, iAcc)

        l = Label(line, textvariable=iGuess, anchor=E, width=8, relief=SUNKEN)
        l.grid(row=0, column=0)
        l = Label(line, textvariable=iRight, anchor=E, width=8, relief=SUNKEN)
        l.grid(row=0, column=1) 
        l = Label(line, textvariable=iWrong, anchor=E, width=8, relief=SUNKEN)
        l.grid(row=0, column=2)   
        l = Label(line, textvariable=iAcc, anchor=E, width=8, relief=SUNKEN)
        l.grid(row=0, column=3)   
        bp = Button(self, text="Run Test", command=self.runTest)
        bp.pack(side=BOTTOM)

        canvas = Canvas(self, width=self.size, height=self.size, bg='lightyellow')
        canvas.pack(expand=YES, fill=BOTH, side=BOTTOM)
        self.canvas = canvas
        
##        slid = Scale(self, label='Wrong', variable=iWrong, to=400, orient=HORIZONTAL, bg='red')
##        slid.pack(side=BOTTOM)
##        slid = Scale(self, label='Right', variable=iRight, to=400, orient=HORIZONTAL, bg='green')
##        slid.pack(side=BOTTOM)

    
    def runTest(self):
        # TODO - This is nasty re-write
        if len(self.guesser) == 0:
            tkMessageBox.showwarning('Underprepared for examination!',
                                     'Your guesser has had no training. Please train and retry.')
            return
        path = tkFileDialog.askdirectory()
        if not path:
            return
        answer = tkSimpleDialog.askstring('Which Pool do these items belong to?', 'Pool name?',
                                          parent=self.app)

        if not answer:
            return
        if answer not in self.guesser.pools:
            return
        
        de = DirectoryExam(path, answer, self.app.itemClass)
        testCount = len(de)
        scale = self.calcScale(testCount)
        x = 0
        y = 0
        cumTime = 0
        iGuess, iRight, iWrong, iAcc = self.model
        for m, ans in de:
            then = time.time()
            g = self.guesser.guess(m)
            cumTime += time.time() - then
            if g:
                g = g[0][0]
                iGuess.set(iGuess.get()+1)
                if g == ans:
                    col = 'green'
                    iRight.set(iRight.get()+1)
                else:
                    col = 'red'
                    iWrong.set(iWrong.get()+1)
                iAcc.set(round(100 * iRight.get()/float(iGuess.get()), 3))

            # Plot squares
            self.canvas.create_rectangle(x*scale,y*scale,(x+1)*scale,(y+1)*scale,fill=col)
            if not divmod(iGuess.get(),(int(self.size/scale)))[1]:
                # wrap
                x = 0
                y += 1
            else:
                x += 1
                
            self.update_idletasks()
        guesses = iGuess.get()
        self.app.status.log('%r guesses in %.2f seconds. Avg: %.2f/sec.' % (guesses, cumTime,
                                                                        round(guesses/cumTime, 2)))

    def calcScale(self, testCount):
        import math
        scale = int(self.size/(math.sqrt(testCount)+1))
        return scale
        
                
    
class DirectoryExam(object):
    """Creates a iterator that returns a pair at a time.
    (Item, correctAnswer). This Exam creates items from
    a directory and uses the same answer for each.
    """
    
    def __init__(self, path, answer, itemClass):
        self.path = path
        self.answer = answer
        self.itemClass = itemClass

    def __iter__(self):
        files = os.listdir(self.path)
        for file in files:
            fp = open(os.path.join(self.path, file), 'rb')
            try:
                item = self.itemClass.fromFile(fp)
            finally:
                fp.close()
            if item is None:
                continue
            yield (item, self.answer)

    def __len__(self):
        files = os.listdir(self.path)
        return len(files)
        
        
        
