import math
from voters import *
import copy

class stv():
    voters = None
    votes = None
    candidates = None
    quota = 0
    scores = None
    winners = None
    had_scores = None

    def __init__(self, voters, quota=None):
        """
        Calculates the Hare winner(s)
        """
        self.voters = voters
        self.candidates = voters.cands.candidates
        self.votes = copy.deepcopy(voters.votes)
        if quota == None:
            self.quota = math.ceil(len(voters.votes)*0.51)
        else: #standard quota is one voter more than half.
            if len(voters.votes) % 2 == 0: #even number of votes
                self.quota = len(voters.votes) * 0.5 + 1
            else: #odd number of votes
                self.quota = math.ceil(len(voters.votes) * 0.5)
        self.scores = {}
        self.winners = []
        self.had_scores = {}
        for c in self.candidates:
            self.had_scores[c] = []


    def __str__(self):
        w = self.winner()
        if w[0] == "STV_tie":
            w.remove("STV_tie")
            return "STV tie: %s" % self.winners[0]
        else:
            return "STV winner: %s" % w


    def score(self):
        first = 1
        while self.winners == []:
            for c in self.candidates:
                self.scores[c] = 0
            for voter in self.votes:
                self.scores[voter.ballot[0]] += 1
            for k,v in self.scores.iteritems():
                #save the different score progressions for plotting
                self.had_scores[k].append(v)
                # remove all the candidates that never got votes
                if v == 0 and first == 1:
                    for voter in self.votes:
                        try:
                            voter.ballot.remove(k)
                        except ValueError:
                            continue#print "Candidate %s cannot be found" % k
                #we found a winner!
                if v >= self.quota:
                    self.winners.append(k)
            if self.winners == []:
                self.remove_lowest()
            first = 0
        return self.scores

    def remove_lowest(self):
        #find the candidate(s) with the lowest score(s)
        lowest_score = []
        low = len(self.votes)
        #and check for a tie
        under_quota = []
        under_quota_scores = []        
        for k,v in self.scores.iteritems():
            if v <= low and v!=0:
                low = v
            if v < self.quota and v!=0:
                under_quota.append(k)
                under_quota_scores.append(v)
        if len(set(under_quota_scores)) == 1:
            self.winners.append("STV_tie")
            self.winners.append(under_quota)
        for k,v in self.scores.iteritems():
            if v == low:
                lowest_score.append(k)
        #reset scores
        for c in self.candidates:
            self.scores[c] = 0
        #remove the lowest scoring ones from the ballots
        for c in lowest_score:
            for voter in self.votes:
                try:
                    voter.ballot.remove(c)
                except ValueError:
                    continue#print "Candidate %s cannot be found" % c

    def winner(self):
        self.score()
        #print "STV:"
        #print self.scores
        return self.winners

