#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright magwas@rabic.org GNU GPL
import pygtk
pygtk.require('2.0')
import gtk
import pango

class Configuration:
    def __init__(self):
        self.rownum=5
        self.fontsize=20
        self.fd=pango.FontDescription("Sans %d"%self.fontsize)

class MainWin:
    def delete_event(self,widget,event,data=None):
        return False

    def destroy(self,widget,data=None):
        gtk.main_quit()

    def __init__(self,children):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)
        self.window.set_border_width(10)

        self.notebook = gtk.Notebook()
        self.window.add(self.notebook)
        self.notebook.show()
        self.window.show()
        self.children=children
        for w,n in children:
            self.add(w.widget,n)

    def main(self):
        gtk.main()

    def add(self,widget,name):
        self.notebook.add(widget)
        self.notebook.set_tab_label_text(widget,name)
        widget.show()
    
class Config:
    def __init__(self,config=None):
        self.config=config
        self.widget=gtk.Table(rows=3,columns=2)
        label=gtk.Label("# of candidates")
        self.widget.attach(label,0,1,0,1)
        self.rownumentry=gtk.Entry()
        self.rownumentry.insert_text('5')
        self.widget.attach(self.rownumentry,1,2,0,1)
        label2=gtk.Label("Font size")
        self.widget.attach(label2,0,1,1,2)
        self.fontsizentry=gtk.Entry()
        self.fontsizentry.insert_text('20')
        self.widget.attach(self.fontsizentry,1,2,1,2)
        self.button=gtk.Button("Legyen")
        self.button.connect('clicked',self.configure,None)
        self.widget.attach(self.button,2,3,0,2)
        label.show()
        label2.show()
        self.rownumentry.show()
        self.fontsizentry.show()
        self.button.show()

    def configure(self,widget,data=None):
        ns=self.rownumentry.get_chars(0,-1)
        if ns == '':
            ns = '0'
        n=int(ns)
        print ns,n
        self.config.rownum=n
        ns=self.fontsizentry.get_chars(0,-1)
        if ns == '':
            ns = '0'
        n=int(ns)
        print ns,n
        self.config.fontsize=n
        self.config.fd=pango.FontDescription("Sans %d"%n)

class Entries:
    def __init__(self, config=None):
        self.config=config
        self.widget=gtk.Table(rows=self.config.rownum,columns=self.config.rownum+1)
        self.widget.connect('map',self.configure,None)
        self.populate()
        self.widget.show()

    def populate(self,fr=0):
        fd=self.config.fd
        for e in self.widget.get_children():
            e.destroy()
        self.children=[]
        for i in range(fr,self.config.rownum):
            cs=[]
            e=gtk.Entry()
            e.modify_font(fd)
            cs.append(e)
            e.set_property("width-chars",30)
            e.show()
            self.widget.attach(e,0,1,i,i+1)
            for j in range(fr,self.config.rownum):
                if i == j:
                    e=gtk.Label(' - ')
                else:
                    e=gtk.Entry()
                    e.set_property("width-chars",3)
                cs.append(e)
                e.modify_font(fd)
                e.show()
                self.widget.attach(e,1+j,2+j,i,i+1,xoptions=0)
            self.children.append(cs)
    def harvest(self):
        l=[]
        for i in self.children:
            ll=[]
            for j in i:
                if j.__class__ == gtk.Label:
                    ll.append("0")
                else:
                    ll.append(j.get_chars(0,-1))
            l.append(ll)
        return l
    def configure(self,widget=None,data=None):
        l=self.harvest()
        self.widget.resize(rows=self.config.rownum,columns=self.config.rownum+1)
        self.populate()
        x=0
        for i in l[:self.config.rownum]:
            y=0
            for j in i[:self.config.rownum+1]:
                k=self.children[x][y]
                if k.__class__ != gtk.Label:
                    k.insert_text(j)
                y += 1
            x += 1

class Result:
    def __init__(self,entries,config=None):
        self.config=config
        self.widget=gtk.Label("ide jon\n az eredmeny")
        self.widget.connect('map',self.compute,None)
        self.entries=entries

    def printmat(self,m):
        l=[]
        for i in range(len(self.candidates)):
            ll=[]
            for j in range(len(self.candidates)):
                if i == j:
                    ll.append('-')
                else:
                    ll.append('%s'%m[i,j])
            l.append(','.join(ll))
        print '\n'.join(l)

    def compute_old(self,widget,data=None):
        self.widget.set_text('computing result')
        self.getdata()
        self.floyd_warshall()
        print self.candidates
        self.printmat(self.d)
        self.printmat(self.p)
        C = len(self.candidates)
        winners=[]
        hasnew = True
        while hasnew:
            hasnew = False
            for i in range(C):
                if i not in winners:
                    isnew = True
                    for j in range(C):
                        if j not in winners:
                            if i != j:
                                if self.p[i,j] < self.p[j,i]:
                                    isnew = False
                    if isnew:
                        winners.append(i)
                        hasnew = True
        print winners
        s=""
        for i in range(len(winners)):
            s += self.candidates[winners[i]]
            if i > 0:
                s += ",by %s:%s"%(self.p[winners[i],winners[i-1]],self.p[winners[i-1],winners[i]])
            s += "\n"
        print s
        self.widget.set_text(s)

    def getdata(self):
        l=self.entries.harvest()
        candidates=[]
        d={}
        x=0
        for line in l:
            candidates.append(line[0])
            y=0
            for pr in line[1:]:
                if pr == '':
                    pr = '0'
                d[x,y]=int(pr)
                y+=1
            x+=1
        self.candidates=candidates
        self.d=d

    def floyd_warshall(self):
        candidates=self.candidates
        C=len(candidates)
        d=self.d
        p={}
        for i in range(C):
            for j in range(C):
                if i != j:
                    if d[i,j] > d[j,i]:
                        p[i,j] = d[i,j]
                    else:
                        p[i,j] = 0
        for i in range(C):
            for j in range(C):
                if i != j:
                    for k in range(C):
                        if i != k:
                            if j != k:
                                p[j,k] = max(p[j,k],min(p[j,i],p[i,k]))
        self.p = p

    def winners(self,ignore):
        n=len(self.candidates)
        winner=[]
        for i in range(n):
            if not ignore.has_key(i):
                won = True
                for j in range(n):
                    if not (ignore.has_key(j) or (i == j)):
                        if self.p[i,j] < self.p[j,i]:
                            won = False
                            break
                if won:
                    winner.append(i)
        return winner

    def rank_candidates(self):
        n=len(self.candidates)
        ignore={}
        num_ranked=0
        result=[]
        while (num_ranked < n):
            winner_list=self.winners(ignore)
            result.append(winner_list)
            for j in winner_list:
                ignore[j] = 1
                num_ranked += 1
        return result

    def _losenum(self,i,j):
        s=" %s: %d "%(self.candidates[j],self.p[j,i])
        #print i,j,s
        return s
    def loosedata(self,ranking,now,n):
        l = []
        if n > 0:
            l +=ranking[n-1]
        if n > 1:
            l +=ranking[n-2]
        s=''
        print l
        for c in l:
            if c != now:
                s += self._losenum(now,c)
        return s
    def compute(self,widget,data=None):
        fd=self.config.fd
        self.widget.modify_font(fd)
        self.widget.set_text('computing result')
        self.getdata()
        self.floyd_warshall()
        print self.candidates
        self.printmat(self.d)
        self.printmat(self.p)
        ranking=self.rank_candidates()
        print ranking
        s="Sorrend:\n"
        n=0
        for r in ranking:
            s += " %d. hely:"%(n+1)
            if len(r) > 1:
                s += "  holtverseny:\n"
            for i in r:
                s+= "    %s (%s)\n"%(self.candidates[i],self.loosedata(ranking,i,n))
            n+=1
        print s        
        self.widget.set_text(s)


                    
def main(go=False):
    conf=Configuration()
    e=Entries(config=conf)
    c=Config(config=conf)
    r=Result(e,config=conf)
    mainwin = MainWin([(c,'config'),(r,"result"),(e,'vote')])
    if go:
        mainwin.main()


if __name__ == "__main__":
    main(True)
