# w.c.s. - web application for online forms
# Copyright (C) 2005-2013  Entr'ouvert
#
# 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, see <http://www.gnu.org/licenses/>.

import os
import sys
import traceback


num_columns = 0
try:
    import curses
except ImportError:
    curses = None
else:
    try:
        curses.setupterm()
        num_columns = curses.tigetnum('cols')
    except:
        pass


from qommon.ctl import Command, make_option

def update_progress(progress):
    if not num_columns:
        return
    sys.stdout.write('[%s] %s%%\r' % (
        ('#'*((num_columns-10)*progress/100)).ljust(num_columns-15), progress))

class CmdConvertToSql(Command):
    name = 'convert-to-sql'

    def __init__(self):
        Command.__init__(self, [
                make_option('--dbname', metavar='DATABASE', action='store',
                            dest='dbname'),
                make_option('--user', metavar='USER', action='store',
                            dest='user'),
                make_option('--password', metavar='PASSWORD', action='store',
                            dest='password'),
                make_option('--host', metavar='HOSTNAME', action='store',
                            dest='host'),
                make_option('--port', metavar='PORT', action='store',
                            dest='port')
                ])

    def execute(self, base_options, sub_options, args):
        import publisher

        self.config.remove_option('main', 'error_log')
        publisher.WcsPublisher.configure(self.config)
        pub = publisher.WcsPublisher.create_publisher(
                register_tld_names=False)

        hostname = args[0]
        pub.app_dir = os.path.join(pub.app_dir, hostname)
        pub.set_config()

        from wcs.formdef import FormDef
        from wcs import sql

        if sub_options.port:
            sub_options.port = int(sub_options.port)

        pub.cfg['postgresql'] = {
                'database': sub_options.dbname,
                'user': sub_options.user,
                'password': sub_options.password,
                'host': sub_options.host,
                'port': sub_options.port,
        }

        sql.get_connection_and_cursor(new=True)

        errors = []

        print 'converting users'
        from users import User
        sql.do_user_table()
        count = User.count()
        for i, user_id in enumerate(User.keys()):
            user = User.get(user_id)
            user.__class__ = sql.SqlUser
            try:
                user.store()
            except AssertionError:
                errors.append((user, traceback.format_exc()))
            update_progress(100*i/count)
        sql.SqlUser.fix_sequences()

        if errors:
            error_log = file('error_user.log', 'w')
            for user, trace in errors:
                print >> error_log, 'user_id', user.id
                print >> error_log, trace
                print >> error_log, '-'*80
            error_log.close()
            print 'There were some errors, see error_user.log for details.'

        errors = []
        for formdef in FormDef.select():
            print ('converting %s' % formdef.name).ljust(num_columns-1)
            sql.do_formdef_tables(formdef, rebuild_views=True,
                    rebuild_global_views=True)
            data_class = formdef.data_class(mode='files')
            count = data_class.count()

            # load all objects a first time, to allow the migrate() code to be
            # run and the eventual changes properly saved.
            for id in data_class.keys():
                formdata = data_class.get(id)
            delattr(sys.modules['formdef'], formdef.url_name.title())

            # once this is done, reload and store everything in postgresql
            sql_data_class = formdef.data_class(mode='sql')
            for i, id in enumerate(data_class.keys()):
                formdata = data_class.get(id)
                formdata._formdef = formdef
                formdata._evolution = formdata.evolution
                formdata.__class__ = sql_data_class
                try:
                    formdata.store()
                except AssertionError:
                    errors.append((formdata, traceback.format_exc()))
                update_progress(100*i/count)
            sql_data_class.fix_sequences()

        print 'done'.ljust(num_columns-1)

        sql.do_tracking_code_table()
        sql.do_meta_table()

        if errors:
            error_log = file('error_formdata.log', 'w')
            for formdata, trace in errors:
                print >> error_log, formdata.formdef, formdata.id
                print >> error_log, trace
                print >> error_log, '-'*80
            error_log.close()
            print 'There were some errors, see error_formdata.log for details.'

        if not pub.has_site_option('postgresql'):
            print 'You still have to edit your site-options.cfg'

        pub.write_cfg()


CmdConvertToSql.register()
