#!/usr/bin/env python
#This file is part of Tryton.  The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
import sys
import os
import time
import threading
import xmlrpclib
import traceback

import gobject

try:
    DIR = os.path.abspath(os.path.normpath(os.path.join(__file__,
        '..', '..', 'neso')))
    if os.path.isdir(DIR):
        sys.path.insert(0, os.path.dirname(DIR))
except:
    pass

# True only if running as a py2exe app
if os.name == 'nt' and hasattr(sys, "frozen"):
    if not ('-v' in sys.argv or '--verbose' in sys.argv or
            '-l' in sys.argv or '--log-level' in sys.argv):
        sys.stdout = open(os.devnull, 'w')
        sys.stderr = open(os.devnull, 'w')
    etc = os.path.join(os.path.dirname(sys.executable), 'etc')
    os.environ['GTK2_RC_FILES'] = os.path.join(etc, 'gtk-2.0', 'gtkrc')
    os.environ['GDK_PIXBUF_MODULE_FILE'] = os.path.join(etc, 'gtk-2.0',
        'gdk-pixbuf.loaders')
    os.environ['GTK_IM_MODULE_FILE'] = os.path.join(etc, 'gtk-2.0',
        'gtk.immodules')

if os.name == 'mac' or \
        (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'):
    resources = os.path.join(os.path.dirname(sys.argv[0]), '..', 'Resources')
    gtkrc = os.path.join(resources, 'gtkrc')
    pixbuf_loader = os.path.join(resources, 'gdk-pixbuf.loaders')
    pangorc = os.path.join(resources, 'pangorc')
    immodules = os.path.join(resources, 'gtk.immodules')
    if os.path.isdir(resources):
        os.environ['GTK2_RC_FILES'] = gtkrc
        os.environ['GTK_EXE_PREFIX'] = resources
        os.environ['GTK_DATA_PREFIX'] = resources
        os.environ['GDK_PIXBUF_MODULE_FILE'] = pixbuf_loader
        os.environ['PANGO_RC_FILE'] = pangorc
        os.environ['GTK_IM_MODULE_FILE'] = immodules

import gtk
from neso.version import VERSION

for i in ('tryton', 'trytond'):
    try:
        DIR = os.path.abspath(os.path.normpath(os.path.join(__file__,
            '..', '..', i, i)))
        if os.path.isdir(DIR):
            sys.path.insert(0, os.path.dirname(DIR))
            continue
    except:  # Exception with py2exe
        pass
    # try for py2exe
    DIR = os.path.join(os.path.abspath(os.path.normpath(
        os.path.dirname(sys.argv[0]))), i, i)
    if os.path.isdir(DIR):
        sys.path.insert(0, os.path.dirname(DIR))
        continue
    # try for py2app
    DIR = os.path.join(os.path.abspath(os.path.normpath(
        os.path.dirname(sys.argv[0]))), '..', 'Resources', i, i)
    if os.path.isdir(DIR):
        sys.path.insert(0, os.path.dirname(DIR))

import tryton.client
TrytonClient = tryton.client.TrytonClient()

from trytond.config import CONFIG
from tryton.config import get_home_dir

DATA_DIR = os.path.join(os.path.abspath(os.path.normpath(
    os.path.dirname(sys.argv[0]))), '.neso')
if not os.path.isdir(DATA_DIR):
    DATA_DIR = os.path.join(unicode(get_home_dir(),
        sys.getfilesystemencoding()), '.neso')
    if not os.path.isdir(DATA_DIR):
        os.mkdir(DATA_DIR, 0700)
VERSION_DATA_DIR = os.path.join(DATA_DIR, VERSION.rsplit('.', 1)[0])
if not os.path.isdir(VERSION_DATA_DIR):
    os.mkdir(VERSION_DATA_DIR, 0700)

CONFIG.options['jsonrpc'] = False
CONFIG.options['xmlrpc'] = False
CONFIG.options['webdav'] = False
CONFIG.options['db_type'] = 'sqlite'
CONFIG.options['data_path'] = VERSION_DATA_DIR

for mod in sys.modules.keys():
    if mod.startswith('trytond.') \
            and not mod.startswith('trytond.config'):
        del sys.modules[mod]

from trytond.pool import Pool
Pool.start()

from trytond.protocols.dispatcher import dispatch
from trytond.exceptions import UserError, UserWarning, NotLogged, \
    ConcurrencyException

import tryton.rpc as rpc
from tryton.exceptions import TrytonServerError


class LocalProxy(xmlrpclib.ServerProxy):

    def __init__(self, host, port, database='', verbose=0,
            fingerprints=None, ca_certs=None):
        self.__host = host
        self.__port = port
        self.__database = database
        self.__verbose = verbose

    def __request(self, methodname, params):
        method_list = methodname.split('.')
        object_type = method_list[0]
        object_name = '.'.join(method_list[1:-1])
        method = method_list[-1]
        args = (self.__host, self.__port, 'local', self.__database, params[0],
            params[1], object_type, object_name, method) + tuple(params[2:])
        try:
            return dispatch(*args)
        except (UserError, UserWarning, NotLogged,
                ConcurrencyException), exception:
            raise TrytonServerError(*exception.args)
        except Exception:
            tb_s = ''
            for line in traceback.format_exception(*sys.exc_info()):
                try:
                    line = line.encode('utf-8', 'ignore')
                except Exception:
                    continue
                tb_s += line
            for path in sys.path:
                tb_s = tb_s.replace(path, '')
            raise TrytonServerError(str(sys.exc_value), tb_s)

    def __repr__(self):
        return "<LocalProxy for %s>" % self.__database

    __str__ = __repr__

    def close(self):
        pass

    @property
    def ssl(self):
        return False

    def __getattr__(self, name):
        # Override to force to use LocalProxy.__request
        return xmlrpclib._Method(self.__request, name)

rpc.ServerProxy = LocalProxy

CRON_RUNNING = True


def cron():
    threads = {}
    while CRON_RUNNING:
        for dbname in Pool.database_list():
            thread = threads.get(dbname)
            if thread and thread.is_alive():
                continue
            pool = Pool(dbname)
            if 'ir.cron' not in pool.object_name_list():
                continue
            cron_obj = pool.get('ir.cron')
            thread = threading.Thread(
                    target=cron_obj.run,
                    args=(dbname,), kwargs={})
            thread.start()
            threads[dbname] = thread
        for i in xrange(60):
            time.sleep(1)
            if not CRON_RUNNING:
                break
thread = threading.Thread(target=cron)
thread.start()

from tryton.config import CONFIG as CLIENT_CONFIG
CLIENT_CONFIG.__setitem__('login.host', False, config=False)
CLIENT_CONFIG.__setitem__('login.server', 'localhost', config=False)
CLIENT_CONFIG.__setitem__('login.port', 8000, config=False)

from tryton.gui.window.dbcreate import DBCreate
_DBCreate_run = DBCreate.run


def DBCreate_run(self):
    self.entry_serverpasswd.set_text('admin')
    self.event_show_button_create(self.dialog, None)
    return _DBCreate_run(self)

DBCreate.run = DBCreate_run

from tryton.gui.window.dbdumpdrop import DBBackupDrop
_DBBackupDrop_run = DBBackupDrop.run


def DBBackupDrop_run(self):
    self.entry_serverpasswd.set_text('admin')
    self.event_show_button_ok(self.dialog, None)
    self.button_ok.set_sensitive(True)
    return _DBBackupDrop_run(self)

DBBackupDrop.run = DBBackupDrop_run

from tryton.gui.window.dbrestore import DBRestore
_DBRestore_run = DBRestore.run


def DBRestore_run(self):
    self.entry_server_password.set_text('admin')
    self.event_show_button_restore(self.dialog, None)
    return _DBRestore_run(self)

DBRestore.run = DBRestore_run

from tryton.common import refresh_dblist
from tryton.gui.window.dblogin import DBLogin
from tryton.exceptions import TrytonError


def DBLogin_run(self):
    self.combo_profile.destroy()
    self.profile_button.destroy()
    self.expander.destroy()
    self.label_host.destroy()
    self.entry_host.destroy()
    self.label_database.destroy()
    self.entry_database.destroy()
    self.profile_label.set_text('Database')
    dbstore = gtk.ListStore(gobject.TYPE_STRING)
    self.database_combo = gtk.ComboBox()
    self.database_combo.set_model(dbstore)
    cell = gtk.CellRendererText()
    self.database_combo.pack_start(cell, True)
    self.database_combo.add_attribute(cell, 'text', 0)

    dbs = refresh_dblist('localhost', 8000)
    if dbs:
        current_db = CLIENT_CONFIG['login.db']
        for idx, dbname in enumerate(dbs):
            dbstore.append((dbname,))
            if current_db == dbname:
                self.database_combo.set_active(idx)
        self.table_main.attach(self.database_combo, 1, 3, 1, 2,
            xoptions=gtk.FILL)
    else:
        dbname = None

        def db_create(button):
            dia = DBCreate('localhost', 8000)
            dbname = dia.run()
            button.hide()
            self.table_main.attach(self.database_combo, 1, 3, 1, 2,
                xoptions=gtk.FILL)
            self.database_combo.show()
            dbstore.append((dbname,))
            self.database_combo.set_active(len(dbstore) - 1)
        image = gtk.Image()
        image.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON)
        create_button = gtk.Button(u'Create')
        create_button.set_image(image)
        create_button.connect('clicked', db_create)
        self.table_main.attach(create_button, 1, 3, 1, 2, xoptions=gtk.FILL)

    self.dialog.show_all()
    self.dialog.reshow_with_initial_size()
    res, result = None, ('', '', '', '', '')
    while not (res in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT)
            or (res == gtk.RESPONSE_OK and all(result))):
        self.database_combo.grab_focus()
        res = self.dialog.run()
        database = self.database_combo.get_active()
        if database != -1:
            db_name = dbstore[database][0]
            CLIENT_CONFIG['login.db'] = db_name
            result = (self.entry_login.get_text(),
                self.entry_password.get_text(), 'localhost', 8000, db_name)

    self.parent.present()
    self.dialog.destroy()
    if res != gtk.RESPONSE_OK:
        rpc.logout()
        raise TrytonError('QueryCanceled')
    return result

DBLogin.run = DBLogin_run

TrytonClient.run()
CRON_RUNNING = False
thread.join()
sys.exit(0)
