#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import hashlib
import json
import os
import random
import time
from itertools import izip

try:
    from __main__ import config
except:
    import ConfigParser as configparser
    config = configparser.RawConfigParser()
    config.read("%s/../../../steve.cfg" % (os.path.dirname(__file__)))
    
import constants, voter
from plugins import *
from backends import *



# Set up DB backend
backend = constants.initBackend(config)


def exists(election, *issue):
    "Returns True if an election/issue exists, False otherwise"
    return backend.document_exists(election, *issue)

def getBasedata(election, hideHash=False):
    "Get base data from an election"
    return backend.get_basedata(election)

def close(election, reopen = False):
    "Mark an election as closed"
    backend.close(election, reopen)
    

def getIssue(electionID, issueID):
    "Get JSON data from an issue"
    issuedata, ihash = backend.issue_get(electionID, issueID)
    if issuedata:
        issuedata['hash'] = ihash
        issuedata['id'] = issueID
        issuedata['APIURL'] = "https://%s/steve/voter/view/%s/%s" % (config.get("general", "rooturl"), electionID, issueID)
        issuedata['prettyURL'] = "https://%s/steve/ballot?%s/%s" % (config.get("general", "rooturl"), electionID, issueID)
        
        # Add vote category for JS magic
        for vtype in constants.VOTE_TYPES:
            if vtype['key'] == issuedata['type']:
                issuedata['category'] = vtype['category']
                break
                
    return issuedata


def getVotes(electionID, issueID):
    "Read votes from the vote file"
    return backend.votes_get(electionID, issueID)

def getVotesRaw(electionID, issueID):
    return backend.votes_get_raw(electionID, issueID)

def getVoteHistory(electionID, issueID):
    return backend.vote_history(electionID, issueID)


def createElection(eid, title, owner, monitors, starts, ends, isopen):
    basedata =  {
            'id': eid,
            'title': title,
            'owner': owner,
            'monitors': monitors,
            'starts': starts,
            'ends': ends,
            'hash': hashlib.sha512("%f-stv-%s" % (time.time(), os.environ['REMOTE_ADDR'] if 'REMOTE_ADDR' in os.environ else random.randint(1,99999999999))).hexdigest(),
            'open': isopen
        }
    backend.election_create(eid, basedata)
    

def updateElection(electionID, basedata):
    backend.election_update(electionID, basedata)


def updateIssue(electionID, issueID, issueData):
    backend.issue_update(electionID, issueID, issueData)


def listIssues(election):
    "List all issues in an election"
    return backend.issue_list(election)

def listElections():
    "List all elections"
    return backend.election_list()


def getVoteType(issue):
    for voteType in constants.VOTE_TYPES:
        if voteType['key'] == issue['type']:
            return voteType
    return None

def vote(electionID, issueID, voterID, vote):
    "Casts a vote on an issue"
    basedata = getBasedata(electionID)
    issueData = getIssue(electionID, issueID)
    if basedata and issueData:
        xhash = hashlib.sha224(electionID + ":" + voterID).hexdigest()
        vhash = hashlib.sha224(xhash + issueID).hexdigest()
        votehash = hashlib.sha224(basedata['hash'] + issueID + voterID + vote).hexdigest()
        
        # Vote verification
        voteType = getVoteType(issueData)
        if voteType.get('vote_func'):
            # This will/should raise an exception if the vote is invalid
            uid = voter.get(electionID, basedata, voterID)
            voteType['vote_func'](basedata, issueID, voterID, vote, uid)
            
        backend.vote(electionID, issueID, voterID, vote, vhash = vhash)
        
        # LURK on who voted :O :O :O
       # if config.has_option("general", "lurk") and config.get("general", "lurk") == "yes":
            #email = voter.get(electionID, basedata, voterID)
          #  backend['lurk'](electionID, email)
       
        return votehash
    else:
        raise Exception("No such election")

    
def validType(issueType):
    for voteType in constants.VOTE_TYPES:
        if voteType['key'] == issueType:
            return True
    return False

def invalidate(issueData, vote):
    for voteType in constants.VOTE_TYPES:
        if voteType['key'] == issueData['type']:
            return voteType['validate_func'](vote, issueData)
    return "Invalid vote type!"

def tally(votes, issue):
    for voteType in constants.VOTE_TYPES:
        if voteType['key'] == issue['type']:
            return voteType['tally_func'](votes, issue)
    raise Exception("Invalid vote type!")

def deleteIssue(electionID, issueID):
    "Deletes an issue if it exists"
    
    if exists(electionID, issueID):
        backend.issue_delete(electionID, issueID)
    else:
        raise Exception("No such election")


def getHash(electionID):
    basedata = getBasedata(electionID)
    issues = listIssues(electionID)
    ihash = ""
    output = []
    for issue in issues:
        issuedata = getIssue(electionID, issue)
        votes = getVotes(electionID, issue)
        ihash += issuedata['hash']
        output.append("Issue #%s: %s\n- Checksum: %s\n- Votes cast: %u\n" % (issue, issuedata['title'], issuedata['hash'], len(votes)))
    tothash = hashlib.sha224(ihash).hexdigest()
    output.insert(0, ("You are receiving this data because you are listed as a monitor for this election.\nThe following data shows the state of the election data on disk. If any of these checksums change, especially the main checksum, then the election has been edited (rigged?) after invites were sent out.\n\nMain Election Checksum : %s\n\n" % tothash))
    output.append("\nYou can monitor votes and recasts online at: %s/monitor.html?%s" % (config.get("general", "rooturl"), electionID))
    return tothash, "\n".join(output)

def createIssue(electionID, issueID, data):
    backend.issue_create(electionID, issueID, data)