import random
from candidates import *
from voter import *
from copy import deepcopy

OUTPUT = 'ballots/dodgson.blt'

class voters:
    num_voters = None
    votes = None
    cands = None

    def __init__(self, cands=None, num_voters=None, votes=None):
        """
        Initializes a new group of voters.
        """
        if cands != None and num_voters != None and votes != None:
            self.cands = cands
            self.num_voters = num_voters
            self.votes = votes
            return
        if cands == None:
            self.cands = candidates() #default
            print "voters did not get cands!!!"
        else:
            self.cands = cands
        if votes != None:
            self.votes = votes
            self.num_voters = len(self.votes)
            return
        if num_voters == None:
            self.num_voters = 5 #default num voters
        else:
            self.num_voters = num_voters
        if votes == None:
            self.votes = []
            for i in range(0, self.num_voters):
                name = "v%i" % i
                self.votes.append(voter(name, self.cands, None, None))

    def __str__(self):
        tmp = []
        for v in self.votes:
            tmp.append(str(v))
        return "%i voters: %s" % (self.num_voters, str(tmp))

    def consolidate_candidates(self, voter):
        """
        Checks to see if the candidates are listed in the vote
        """
        if len(self.cands) != len(voter.ballot):
            print "This voter is corrupted!"
        else: 
            tmpc = self.cands
            tmpv = voter.ballot
            for cand in self.cands:
                for (i, j) in tmpv:
                    if j == cand:
                        tmpc.pop(cand)
                        break
            if tmpc != []:
                print "ahh more drama!"

    def output_ballots(self, out=OUTPUT):
        """
        writes the voters to a file in the format of one voter per line
        with first the most popular candidates
        candidates considered most interesting are on the left
        equally ranked candidates are placed within []
        and approval is considered for candidates listed before a %
        """
        f = open(out, "w")
        for voter in self.votes:
            voter.collapse()
            prev = 0
            dict = {}
            for (i, j) in voter.ballot:
                if prev == i:
                    dict[i].append(j)
                else:
                    dict[i] = [j]
                prev = i
            cut = voter.cutoff
            for i in range(len(self.cands.candidates), 0, -1):
                if cut == 0:
                    f.write('%,')
                if len(dict[i]) > 1:
                    f.write("[")
                    for c in i:
                        f.write(c),
                        f.write(",")
                    f.write("]")
                else:
                    f.write(dict[i][0])
                if i > 1:
                    f.write(",")
                cut-=1
            f.write("\n")
        f.close()

    def output_blt(self, out):
        f = open(out, "w")
        for voter in self.votes:
            c = voter.cutoff
            for i in range(0,len(voter.ballot)):
                if c == 0:
                    f.write('%,')
                f.write(voter.ballot[i])
                if i < len(voter.ballot)-1:
                    f.write(",")
                c -= 1
            f.write("\n")
        f.close()



    @staticmethod
    def parser(INPUT,cands=None):
        f = open(INPUT, "r")
        lines = f.readlines()
        ballots = []
        for line in lines:
            ballots.append(line.strip().split(","))
        #find the candidates of the election
        if cands == None:
            try:
                c = deepcopy(ballots[0])
                c.remove('%')
            except ValueError:
                c = ballots[0]
        else:
            c = cands
        #find the rankings and the approval cutoffs
        vlist = []
        for ballot in ballots:
            try:
                cut = ballot.index('%')
                ballot.remove('%')
            except ValueError:
                cut = len(ballot)
            name = "v%i" % random.randint(100,999)
            vlist.append(voter(name, c, ballot, cut))
        v = voters(candidates(c), len(ballots), vlist)
        return v

    def add_ballots(self, INPUT):
        f = open(INPUT, "r")
        lines = f.readlines()
        ballots = []
        for line in lines:
            ballots.append(line.strip().split(","))
        #extract candidate list from first vote
        try:
            c = ballots[0].remove('%')
        except ValueError:
            c = ballots[0]
        c.sort()
        self.cands.sort()
        if c != self.cands:
            print "candidate mismatch while adding ballots!"
        else:
            for ballot in ballots:
                try:
                    cut = ballot.index('%')+1
                    ballot.remove('%')
                except ValueError:
                    cut = len(ballot)
                name = "v%i" % random.randint(100,999)
                self.votes.append(voter(name, c, ballot, cut))

