#!/bin/env python3
# -*- coding: utf-8 -*-
#    TOMUSS: The Online Multi User Simple Spreadsheet
#    Copyright (C) 2011-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@univ-lyon1.fr

import os
import re
import ast
from . import tableexport
from .. import utilities
from .. import document
from .. import plugin
from .. import configuration
from ..COLUMN_TYPES import upload

class TableCopy(tableexport.TableExport):
    default_value = 1
    name = 't_copy'
    action = 'table_copy'
    gui_display = "GUI_a"
    css = """
DIV.import_export TABLE.table_copy_diagram {
 width: 35em; border-spacing:0.4em; margin: auto; background: #CCC }
TABLE.table_copy_diagram TD { text-align: center; vertical-align: middle; }
TABLE.table_copy_diagram TH { background: white ; border: 1px solid #888; }
    """

##################################### PLUGIN ################################

def tablecopy(server):
    """Copy the table in another EMPTY one"""
    _ = utilities._

    server.the_file.write('<pre>' + _("MSG_tablecopy_start") + "\n")
    table = document.table(server.the_year, server.the_semester,
                           server.the_ue, None, None)
    if not table.readable_by(server.ticket):
        server.the_file.write('Hacker!')
        return
    if table.is_unique():
        server.the_file.write(_("LABEL_table_ro"))
        return
    server.the_file.write(_("MSG_tablecopy_read") + "\n")

    dest_year = int(server.the_path[0])
    dest_semester = utilities.safe(server.the_path[1]).replace('.','_')
    option = server.the_path[2]
    if len(server.the_path) == 4 and len(server.the_path[3]):
        newname = utilities.safe(server.the_path[3])
    else:
        newname = server.the_ue
        if dest_year == server.the_year and dest_semester==server.the_semester:
            server.the_file.write(_("MSG_tablecopy_cant") + "\n")
            return

    dest_table = document.table(dest_year,dest_semester, newname, create=False)
    if dest_table:
        if not dest_table.empty(empty_even_if_used_page=True,
                                empty_even_if_created_today=True,
                                empty_even_if_column_created=True)[0]:
            server.the_file.write(_("MSG_tablecopy_not_empty") + "\n")
            return
        dest_table.delete() # Moved to Trash: inode kept

    if option != 'columns':
        for column in table.columns:
            if column.private:
                server.the_file.write('<p style="background:#F88"><b>Content copy not allowed if a private column exists.</b><br>'
                    + option + ' → columns</p>\n')
                option = 'columns'
                break

    if option in ('history', 'upload'):
        c = utilities.read_file(table.filename)
    elif option == 'content':
        c = table.rewrite(user_name=server.ticket.user_name)
    elif option == 'columns':
        c = table.rewrite(only_columns=True, user_name=server.ticket.user_name)
    else: # pragma: no cover
        server.the_file.write("\nBUG: '%s'." % option)
        return

    # Rewrite dynamic column import
    # 2022 Automne   → 2023 Printemps :  +1 semester (+1 year +1 semester)
    # 2022 Automne   → 2023 Automne   :  +2 semester (+1 year +0 semester)
    # 2023 Printemps → 2023 Automne   :  +1 semester (+0 year +1 semester)
    # XXX Only works with normal semesters (not Dossiers/Public/...)
    start_year = server.the_year
    start_semester = server.the_semester
    for nr_semesters in range(100):
        if start_year == dest_year and start_semester == dest_semester:
            break
        start_year, start_semester = utilities.next_year_semester(start_year, start_semester)
    else:
        nr_semesters = None

    if nr_semesters: # pragma: no cover
        def update_url(text):
            """Update a single reference"""
            if not text:
                return text
            url = text.split('/')
            if len(url) < 3: # Absolute minimum: Semester/UE/Column
                return text
            if url[0] in configuration.semesters:
                url.insert(0, str(server.the_year)) # Insert missing year
            if url[0].isdigit():
                if url[1] in configuration.semesters:
                    start_year = int(url[0])
                    start_semester = url[1]
                    for _ in range(nr_semesters):
                        start_year, start_semester = utilities.next_year_semester(
                            start_year, start_semester)
                    url[0] = str(start_year)
                    url[1] = start_semester
                    return '/'.join(url)
            # Web url or not standard semester
            return text

        def update_year_semester(rematch):
            """Replace the year and semester"""
            line = rematch.group()
            infos = list(ast.literal_eval(line.replace('\ncolumn_attr', '')))
            if infos[3][0] in '#@?:':
                prefix = infos[3][0]
                infos[3] = infos[3][1:]
            else:
                prefix = ''
            urls = [update_url(url) for url in infos[3].split(' ')]
            infos[3] = prefix + ' '.join(urls)
            return '\ncolumn_attr' + repr(tuple(infos)) + '\n'
        c = re.sub("\ncolumn_attr\\('url_import',.*\n", update_year_semester, c)

    filename = document.table_filename(dest_year, dest_semester, newname)
    try:
        utilities.write_file(filename, c) # New inode ⇒ suivi server reload
    except IOError: # pragma: no cover
        server.the_file.write(_("MSG_tablecopy_cant") + "\n")
        return
        
    server.the_file.write(_("MSG_tablecopy_check") % (len(c)/1024.) + "\n")
    dest_table = document.table(dest_year,dest_semester, newname, create=False)

    for name in dest_table.masters:
        dest_table.master_of_update('+', name)

    if dest_table.official_ue:
        for login in dest_table.the_keys():
            document.indexes_to_update.append((dest_table, '', login))
        utilities.start_job(document.check_indexes_to_update, 0)

    server.the_file.write("\n" + _("MSG_tablecopy_done") + "\n")
    url = "%s/%s/%s/%s" % (configuration.server_url, dest_year, dest_semester,
                           newname)
    server.the_file.write('<a target="_blank" href="%s">%s</a>' % (
            server.ticket.url(url), url))
    if option != 'upload':
        return
    # Copy uploaded files
    server.the_file.write('</pre><p style="width:100%">')
    for column in table.columns:
        if column.type.name != 'Upload':
            continue
        dirname = upload.container_path(column)
        new_dir = upload.container_path(dest_table.columns[column.data_col])
        utilities.mkpath(new_dir, create_init=False)
        for lin_id, cells in table.lines.items():
            if cells[column.data_col].value and cells[column.data_col].comment:
                filename = os.path.join(dirname, lin_id)
                if os.path.exists(filename):
                    utilities.write_file(os.path.join(new_dir, lin_id),
                                         utilities.read_file(filename, encoding="bytes"),
                                         encoding="bytes")
                    server.the_file.write(' ' + cells[column.data_col].comment.split(';')[0])

plugin.Plugin('tablecopy', '/{Y}/{S}/{U}/tablecopy/{*}',
              function=tablecopy, group='staff',
              )


def remove_history(server):
    """Remove the history of the table.
    Do not call from a thread.

    Beware: users with non unclosed table will have bad_allow.html answer
    when trying to use the old table with the new one.
    """
    server.the_file.write('<h1>' + server._("MSG_remove_history") + '</h1>')
    table = document.table(server.the_year, server.the_semester,
                           server.the_ue, None, None)

    if server.ticket.user_name not in table.masters:
        server.the_file.write(server._("MSG_extension_not_master"))
        return
    if not table.modifiable:
        server.the_file.write(server._("TIP_table_attr_modifiable"))
        return
    if len(table.active_pages) > 1:
        server.the_file.write(server._('MSG_remove_history_open')
                              % ('<ul>'
                                 + ''.join('<li> %s %s' % (page.user_name,
                                                           page.date)
                                           for page in table.active_pages
                                       )
                                 + '</ul>'
                                 )
                              + '<br>') # pragma: no cover
    if 'ok' in server.the_path:
        table.unload(force=True)
        utilities.unlink_safe(table.filename)
        f = open(table.filename, "w", encoding = "utf-8")
        f.write(table.rewrite())
        f.close()
        server.the_file.write(server._("MSG_tablecopy_done"))
        table.unload_on_suivi()
    else:
        server.the_file.write('<p><a href="' + server.ticket.url('ok') + '">'
                        + server._('MSG_remove_history_confirm')
                        + '</a>')

plugin.Plugin('remove_history', '/{Y}/{S}/{U}/remove_history/{*}',
              function=remove_history, group='staff',
              )
