#!/usr/bin/env python
# -*- coding: utf-8 -*-
#    TOMUSS: The Online Multi User Simple Spreadsheet)
#    Copyright (C) 2008-2013 Thierry EXCOFFIER, Universite Claude Bernard
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program 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.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#    Contact: Thierry.EXCOFFIER@bat710.univ-lyon1.fr

# import locale
# locale.setlocale(locale.LC_ALL, 'fr_FR.utf8')

import tomuss_init
import os
import sys
import time
import re
import BaseHTTPServer
from . import configuration
from . import utilities
from . import authentication
from . import plugin
from . import ticket

if False:
    from . import deadlock
    deadlock.start_check_deadlock()

warn = utilities.warn

StaticFile = utilities.StaticFile

running = True

class MyRequestBroker(utilities.FakeRequestHandler):
    def log_time(self, action):
        time_logs.write('%f %g %s\n' % (self.start_time, time.time()
                                   - self.start_time, action))
        time_logs.flush()

    def do_GET(self):
        try:
            self.do_GET_real()
        except:
            utilities.send_backtrace('',
                                     subject='GET path = ' + self.path)

    def do_GET_real(self):
        if ticket.client_ip(self) in configuration.banned_ip:
            return
        self.start_time = time.time()
        self.the_port = server_port
        self.ticket = None

        if self.path.startswith('/PROFILE_THIS_URL/'):
            self.path = self.path.replace('/PROFILE_THIS_URL/', '/')
            self.do_profile = True
        else:
            self.do_profile = False

        # APACHE make a mess with %2F %3F and others
        # so we encode them with $2F $3F...
        self.path = self.path.replace("$", "%")
        self.the_path = self.path.split('/')[1:]

        # Remove year/semester if present
        # They are only useful to use an Apache dispatch on the good port
        ip = 0
        if self.the_path[0].startswith('='):
            ip += 1
        try:
            self.year = int(self.the_path[ip])
            self.semester = self.the_path[ip+1]
            # The 'rss2' plugin need year/semesters not in configuration.semesters
            # if self.semester not in configuration.semesters:
            #    raise ValueError('')
            del self.the_path[ip:ip+2]
        except (ValueError, IndexError):
            self.year, self.semester = configuration.year_semester
        path = '/' + '/'.join(self.the_path)

        if path[1:] == 'load_config':
            to_reload = ('config_table', 'config_plugin', 'config_acls',
                         'config_cache')
            for tt in to_reload:
                conf = document.table(0, 'Dossiers', tt, None, None, ro=True)
                conf.do_not_unload = []
                conf.unload()
            for tt in to_reload:
                document.table(0, 'Dossiers', tt, None, None, ro=True)
            
            configuration.config_acls_clear_cache()
            self.send_response(200)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            self.wfile.write('ok')
            return

        if path[1:] == 'robots.txt':
            self.send_response(200)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            self.wfile.write(utilities.read_file(os.path.join("FILES",
                                                              "robots.txt")))
            return

        if configuration.regtest and path == '/stop':
            global running
            self.send_response(200)
            self.send_header('Cache-Control', 'no-cache')
            self.send_header('Cache-Control', 'no-store')
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            self.wfile.write('stopped')
            running = False
            return
        
        self.the_file = self.wfile
        self.the_rfile = self.rfile
        # self.do_not_close_connection()
        if plugin.dispatch_request(self, manage_error=False) is None:
            # XXX Assumes that a thread is not launched
            return # Unauthenticated dispatch is done

        self.path = path
        the_ticket, self.the_path = ticket.get_ticket_string(self)
        self.ticket = ticket.get_ticket_objet(the_ticket, self)
        warn('ticket=%s' % str(self.ticket)[:-1])
        warn('the_path=%s' % str(self.the_path))

        # Restore year/semester in order to have a good redirection
        if configuration.regtest:
            self.path = '/%d/%s' % (self.year, self.semester) + path
        else:
            # Remove old ticket.
            self.path = '/%d/%s' % (
                self.year, self.semester) + re.sub("^/=[^/]*", "", path)
        if authentication.ok(self):
            self.do_GET_real_real_safe()

        # Free some memory
        now = time.time()
        if now - server.last_unload > 60:
            nb = 0
            nb_unloaded = 0
            for t in document.tables_values():
                nb += 1
                if now - getattr(t,"rtime",0) > configuration.unload_interval:
                    t.unload()
                    nb_unloaded += 1
            server.last_unload = now
            warn("%d table unloaded on %d" % (nb_unloaded, nb), what="info")

    def do_GET_real_real_safe(self):
        tick = self.ticket
        logs.write(time.strftime('%Y%m%d%H%M%S ') + tick.user_name + '\n')
        plugin.dispatch_request(self)

if __name__ == "__main__":
    try:
        if sys.argv[1] == 'any' and sys.argv[2] == 'any':
            year = semester = year_semester = None
        else:
            year = int(sys.argv[1])
            semester = sys.argv[2]
            year_semester = "%d/%s" % (year, semester)
        server_port = int(sys.argv[3])
    except:
        sys.stderr.write("%s yearYYYY|any semester|any TCPport\n"% sys.argv[0])
        sys.exit(1)

    for i in sys.argv:
        if i == 'regtest':
            configuration.regtest = True
    from . import regtestpatch
    regtestpatch.do_patch()
    configuration.read_only = True
    from . import document
    from . import plugins
    plugins.load_types()
    document.table(0, 'Dossiers', 'config_table', None, None,
                   ro=True, create=False)
    document.table(0, 'Dossiers', 'config_acls', None, None,
                   ro=True, create=False)
    warn("Configuration table loaded, do_not_display=%s" % repr(configuration.do_not_display))
    utilities.init()


    utilities.mkpath(os.path.join("LOGS", "SUIVI%d" % server_port))
    logs = open(os.path.join("LOGS", "SUIVI%d" % server_port,
                             str(time.localtime()[0]) + '.connections'), "a")
    time_logs = open(os.path.join("LOGS", "SUIVI%d" % server_port,
                                  str(time.localtime()[0]) + '.times'), "a")

    plugins.plugins_suivi()
    document.table(0, 'Dossiers', 'config_plugin', None, None,
                   ro=True, create=False)
    document.table(0, 'Dossiers', 'config_cache', None, None,
                   ro=True, create=False)

    authentication.run_authentication()

    server = BaseHTTPServer.HTTPServer(("0.0.0.0", server_port),
                                       MyRequestBroker)
    server.last_unload = 0

    StaticFile._url_ = configuration.suivi.url(year, semester, ticket='')
    authentication.authentication_redirect = '/'.join(StaticFile._url_.split('/')[:-2])
    
    plugins.generate_data_files(suivi=True)

    if configuration.regtest:
        # 'Suivi' regtest fail because list of modified UE
        # is not displayed for teachers
        configuration.index_are_computed = False

    if not configuration.index_are_computed:
        from . import tablestat

        # Load all the tables, in order to allow fast access
        for t in tablestat.les_ues(year, semester):
            if False:
                warn("%s grpcol=%s seqcol=%s" % (t.ue, t.columns.get_grp(),
                                                 t.columns.get_seq()))

    warn("Server Ready on: " + authentication.authentication_redirect)
    while running:
        server.handle_request()
    utilities.stop_threads()




