#! /usr/bin/env python
# -*- coding:utf-8 -*-

import codecs
import csv
import urllib
import urllib.request
import urllib.parse
import os
import sys
import time
import http.cookiejar
import shlex

import gspread

class Write2Spread(object):
    def __init__(self, username, password, url, sheetnum):
        try:
            gc = gspread.login(username, password)
            self.ws = gc.open_by_url(url).get_worksheet(int(sheetnum))
        except gspread.exceptions.AuthenticationError:
            print("Oops! Incorrect username or password. Please try again.",
                  file=sys.stderr)

    def append_row(self, values):
        """
        値のリストをスプレットシートの最後の列として追加する.

        :param values: 書き込みたい値のリスト.長さはスプレットシートのカラムを超えなければよい.
        """
        self.ws.append_row(values)

class Atcoder(object):
    def __init__(self, contest_name):
        cookie = http.cookiejar.CookieJar()
        self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie))
        self.contest_name = contest_name

    def login(self, username, password):
        post = {
            'name': username,
            'password': password
        }
        data = urllib.parse.urlencode(post).encode('UTF-8')
        self.opener.open(self.__contest_url() + "login", data)

    def get_standings(self):
        res = self.opener.open(self.__contest_url() + "standings/csv/")
        lines = res.read().decode("Shift-JIS").splitlines()

        reader = csv.reader(lines)
        # Skip header
        next(reader)
        return [team_score for team_score in reader]

    def __contest_url(self):
        return "http://" + self.contest_name + ".contest.atcoder.jp/"

def get_old_csv():
    res = ""
    with codecs.open(OLD_STANDINGS_FILE_NAME, 'r') as f:
        reader = csv.reader(f)
        res = [team for team in reader]
    return res

def update_csv(new_content):
    with codecs.open(OLD_STANDINGS_FILE_NAME, 'w') as f:
        f.seek(0)
        writer = csv.writer(f)
        for row in new_content:
            writer.writerow(row)
        f.truncate()

def find_score(teamid, standings):
    for score in standings:
        if len(score) > 3 and score[2] == teamid:
            return score
    return []

def get_diff(score1, score2):
    length = len(score1)
    res = []
    for idx, s1, s2 in zip(range(0, length-5), score1[4:], score2[4:]):
        if s1 != s2:
            res.append(idx)
    return res

def get_updates(atcoder):
    standings = atcoder.get_standings()
    old_standings = get_old_csv()

    res = []
    for team in standings:
        if len(team) < 3:
            continue
        teamname = team[1]
        teamid = team[2]
        score = find_score(teamid, standings)
        old_score = find_score(teamid, old_standings)
        d = list(map(lambda x: PROBLEM_IDS[int(x / 3)],
                     [x for x in get_diff(score, old_score)
                      if x % 3 == 0 and x / 3 < len(PROBLEM_IDS)]))
        if len(d) > 0:
            res.append([teamid, teamname, d])
    return (res, standings)

PROBLEM_IDS = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
OLD_STANDINGS_FILE_NAME = "old.csv"

def update_spreadsheet(w2s, updates):
    try:
        for update in updates:
            print(update)
            if len(update) > 0:
                for problem in update[2]:
                    w2s.append_row([update[0], update[1], problem])
    except:
        raise

def say(updates):
    for update in updates:
        os.system('say -v Victoria ' + quote(update[0])

def main():
    google_user_name = 'a@b.c'
    google_password = 'your google password'
    spreadsheet_url = 'URL of the spreadsheet'
    spreadsheet_sheetnum = 0
    w2s = Write2Spread(google_user_name, google_password, spreadsheet_url,
                       spreadsheet_sheetnum)

    atcoder = Atcoder('')
    atcoder_user_name = 'atcoder user id'
    atcoder_password = 'atcoder password'
    atcoder.login(atcoder_user_name, atcoder_password)

    interval = 3
    while True:
        try:
            updates, standings = get_updates(atcoder)
            update_spreadsheet(w2s, updates)
            say(updates)
            update_csv(standings)
            print(".", end="", flush=True)
            time.sleep(interval)
        except KeyboardInterrupt:
            print("Bye")
            sys.exit()

if __name__ == "__main__":
    main()