#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  Copyright (C) 2012 by Atzm WATANABE <atzm@atzm.org>
#
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License (version 2) as
#  published by the Free Software Foundation.  It is distributed in the
#  hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
#  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#  PURPOSE.  See the GNU General Public License for more details.
#
# $Id$
#

from __future__ import with_statement

import os.path
import sys
import cgi
import json
import fcntl
import urllib
import ConfigParser


class ScoreBoard(object):
    def __init__(self, path, limit):
        self._path = path
        self._limit = limit
        self._data = []
        self._fp = None

    def get(self):
        return self._data[:]

    def open(self, mode='a+', lock=fcntl.LOCK_EX):
        self._fp = open(self._path, mode)
        fcntl.flock(self._fp, lock)
        return self

    def close(self):
        self._fp.close()
        return self

    def read(self):
        self._fp.seek(0, 0)
        raw = self._fp.read()
        if raw:
            self._data = json.loads(raw)
        return self

    def write(self):
        raw = json.dumps(self._data, ensure_ascii=False).encode('utf-8')
        self._fp.seek(0, 0)
        self._fp.truncate(0)
        self._fp.write(raw + '\n')
        return self

    def insert(self, name, value, stime, etime):
        self._data.append({
            'name':  name,
            'value': value,
            'stime': stime,
            'etime': etime,
        })

        self.sort()

        if self._limit < len(self._data):
            self._data.pop(-1)

        return self

    def sort(self):
        self._data.sort(lambda a, b: cmp(a['value'], b['value']), reverse=True)
        return self


def main():
    config = ConfigParser.SafeConfigParser()
    config.read('score.conf')

    path = os.path.abspath(os.path.expanduser(config.get('DEFAULT', 'path')))
    limit = config.getint('DEFAULT', 'limit')
    board = ScoreBoard(path, limit)

    form = cgi.FieldStorage()

    try:
        stime = int(form.getfirst('stime'))
        etime = int(form.getfirst('etime'))
        score = int(form.getfirst('value'))
        name = urllib.unquote(form.getfirst('name')).decode('utf-8')
        if 20 < len(name):
            raise ValueError('name is too long')
        board.open().read().insert(name, score, stime, etime).write().close()
    except:
        board.open().read().close()

    sys.stdout.write('Content-type: application/json; charset=UTF-8\r\n\r\n')
    print(json.dumps(board.get(), ensure_ascii=False).encode('utf-8'))


if __name__ == '__main__':
    main()
