import MyRaft.state as state
import MyRaft.leader as leader
# import MyRaft.follower as follower
import MyRaft.node as node
import MyRaft.raft_pb2 as raft_pb2

class Candidate(state.State):
    def __init__(self, context:node.RaftNode, majority = 2):
        state.State.__init__(self, context)
        print("We're a candidate!")
        context.currentTerm += 1
        self._votes_received = [] # List of voters who have voted.
        self._votes_received.append(self._context._id)
        self._majority = majority
        self._context.set_timeout(self._context._min_timout, self._context._vary_timeout)
        print("Sending RequestVote to other nodes")
        self._context.send_RequestVote()

    def rcv_vote(self, request):
        print("Received Vote")
        # Checks the term...
        if not request.voteGranted:
            print("They rejected us!")
        if request.voterId not in self._votes_received:
            print("Added a vote!")
            self._votes_received.append(request.voterId)
        if len(self._votes_received) >= self._majority:
            self._context.set_state(leader.Leader(self._context))

    def heartbeat_elapsed(self):
        # Start a new election.
        self._context.currentTerm += 1
        self._context.set_timeout(self._context._min_timout, self._context._vary_timeout)
        print("Sending RequestVote to other nodes")
        self._context.send_RequestVote()

    def rcv_AppendEntries(self, request):
        if request.term >= self._context.currentTerm:
            self._context.set_state(follower.Follower(self._context))

    def rcv_RequestVote(self, request):
        print("Received a vote request")
        if request.term > self._context.currentTerm:
            print("They're more important, going back to a follower")
            self._context.set_state(follower.Follower(self._context))
            self._context.votedFor = request.candidateId
            return raft_pb2.RequestVoteResponse(term = self._context.currentTerm,
                                                voteGranted = True,
                                                voterId = self._context._id)