#!/usr/bin/python
# -*- coding: utf-8 *-*

"""
Interface graphique, basée sur Tk, pour utiliser le module loan.py
"""

from Tkinter import *
from tkFont import *
from loan import LoanError, Loan

class LoanApp(Tk):
    """
Application graphique pour interface avec loan.py
    """
    def __init__(self, master = None):
        Tk.__init__(self, master)
        self.loan = Loan()
        self.setup()

    def setup(self):
        """
Mise en place de tous les petits boutons et autres widgets
        """
        normal_font = Font(self, family = 'helvetica', size = 12)
        bold_font = Font(self, family = 'Helvetica', size = 12,
                         weight = BOLD)

        r = 0 # Compteur de ligne

        # Les entrées
        for (name, label) in [("cap", "Capital"), ("rate", "Taux annuel"),
                              ("time", "Temps"), ("prime", "Mensualité")]:

            label = Label(self, text = label, font = bold_font)
            label.grid(row = r, column = 0,
                       padx = 10, pady = 5, sticky = "w")
            entry = Entry(self, relief = SUNKEN, highlightthickness = 0,
                          font = normal_font, background = "white")
            entry.grid(row = r, column = 1, padx = 10, sticky = "we")
            setattr(self, name + '_entry', entry)
            r += 1

        # Affichage du total
        total_label = Label(self, text = "Total", font = bold_font)
        total_label.grid(row = r, column = 0,
                         padx = 10, pady = 5, sticky = "w")
        self.total_value = Label(self, relief = SUNKEN, font = normal_font,
                                 anchor = "w", background = "white")
        self.total_value.grid(row = r, column = 1, padx = 10, sticky = "we")
        r += 1

        # Légende des boutons
        label = Label(self, text = "Calculer", anchor = "center",
                      font = bold_font)
        label.grid(row = r, column = 0, columnspan = 2, pady = 10)
        r += 1

        # La ligne contentant les boutons
        bline = Frame(self)
        bline.grid(row = r, column = 0, columnspan = 2)
        r += 1

        # Les boutons
        for (name, label, format, loan_attr, loan_func) in [
              ("prime", "Mensualité", "%.2f",
               self.loan.prime, self.loan.compute_prime),
              ("time", "Nb de mensualités", "%d",
               self.loan.time, self.loan.compute_time),
              ("rate", "Taux annuel", "%.2f",
               self.loan.year_rate, self.loan.compute_rate)
            ]:
            command = self.compute_command(loan_attr, loan_func, format,
                                           getattr(self, name +'_entry'))
            button = Button(bline, text = label, command = command,
                            font = bold_font)
            button.pack(side = "left", padx = 10)
            setattr(self, name + '_but', button)
            setattr(self, name + "_command", command)

        # Les messages
        self.status = Label(self, anchor = "w", text = "", padx = 5,
                            relief = SOLID, borderwidth = 1, height = 2,
                            font = normal_font, wrap = 400)
        self.status.grid(row = r, column = 0, columnspan = 2,
                         sticky = "nesw", padx = 5, pady = 5)

        # Ajustements
        self.columnconfigure(0, minsize = 60)
        self.columnconfigure(1, weight = 70)
        self.rowconfigure(r, weight = 100)

        # Raccourcis
        self.cap_entry.bind("<Return>", self.prime_command)
        self.rate_entry.bind("<Return>", self.prime_command)
        self.time_entry.bind("<Return>", self.prime_command)
        self.prime_entry.bind("<Return>", self.rate_command)

    def compute_command(self, loan_attr, loan_method, format, entry):
        """
Rend un "callback" pour les boutons de calcul
        """
        def command(event = None):
            try:
                self.check_entries()
                loan_method()
                entry.delete(0, len(entry.get()))
                entry.insert(0, format % loan_attr())

                total = self.loan.total()
                if total is not None:
                    self.total_value.configure(text = "%.2f" % total)
                else:
                    self.total_value.configure(text = "")
            except LoanError, e:
                self.message(str(e))
        return command

    def check_entries(self):
        for (name, loan_attr, desc) in [
              ("cap", self.loan.capital, "capital emprunté"),
              ("time", self.loan.time, "nb de mensualités"),
              ("prime", self.loan.prime, "montant des mensualités"),
              ("rate", self.loan.year_rate, "taux annuel")
            ]:
            entry = getattr(self, name + '_entry')
            s = entry.get()
            if s:
                loan_attr(s)
            else:
                setattr(self.loan, '_' + name, None)
            self.message("")

    def message(self, msg):
        self.status.configure(text = msg)