#!/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 logging
import time
import threading

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"):
    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 *

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['netrpc'] = 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.backend import Database

import tryton.rpc as rpc

def db_list(host, port):
    Database._memory_database = None
    return dispatch('127.0.0.1', 8070, 'local', None, None, None, 'common', 'db',
            'list')

rpc.db_list = db_list

def db_exec(host, port, method, *args):
    Database._memory_database = None
    args = ('127.0.0.1', 8070, 'local', None, None, None, 'common', 'db', method) \
            + args
    return dispatch(*args)

rpc.db_exec = db_exec

def server_version(host, port):
    return dispatch('127.0.0.1', 8070, 'local', None, None, None, 'common', None,
            'version')
rpc.server_version = server_version

def login(username, password, host, port, database):
    res = dispatch('127.0.0.1', 8070, 'local', database, username, password,
            'common', 'db', 'login')
    if not res:
        rpc._USER = 0
        rpc._SESSION = ''
        return -2
    rpc._USER = res[0]
    rpc._USERNAME = username
    rpc._SESSION = res[1]
    rpc._DATABASE = database
    rpc.context_reload()
    return 1

rpc.login = login

def logout():
    if rpc._SOCK and rpc._USER:
        dispatch('127.0.0.1', 8070, 'local', rpc._DATABASE, rpc._USERNAME,
                rpc._SESSION, 'common', 'db', 'logout')
    rpc._USER = 0
    rpc._USERNAME = ''
    rpc._SESSION = ''
    rpc._DATABASE = ''
    rpc._VIEW_CACHE = {}
    rpc.SECURE = False

rpc.logout = logout

def _execute(blocking, *args):
    logging.getLogger('rpc.request').info(repr((args)))
    key = False
    if len(args) >= 6 and args[1] == 'fields_view_get':
        key = str(args)
        if key in rpc._VIEW_CACHE and rpc._VIEW_CACHE[key][0]:
            args = args[:]
            args = args + (rpc._VIEW_CACHE[key][0],)
    res = rpc._SEMAPHORE.acquire(blocking)
    if not res:
        return
    try:
        result = dispatch(*(('127.0.0.1', 8070, 'local', rpc._DATABASE,
            rpc._USER, rpc._SESSION) + args))
    finally:
        rpc._SEMAPHORE.release()
    if key:
        if result is True and key in rpc._VIEW_CACHE:
            result = rpc._VIEW_CACHE[key][1]
        else:
            rpc._VIEW_CACHE[key] = (result['md5'], result)
    logging.getLogger('rpc.result').debug(repr(result))
    return result

rpc._execute = _execute

class _SOCK(object):
    hostname = 'localhost'
    host = '127.0.0.1'
    port = 8070

rpc._SOCK = _SOCK()

CRON_RUNNING = True
def cron():
    while CRON_RUNNING:
        for dbname in Pool.database_list():
            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.pool_jobs,
                    args=(dbname,), kwargs={})
            thread.start()
        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', '8070', config=False)

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

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

DBCreate.run = DBCreate_run

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

def DBBackupDrop_run(self, parent):
    self.entry_serverpasswd.set_text('admin')
    self.entry_server_connection.set_text('127.0.0.1:8070')

    liststore = gtk.ListStore(str)
    self.combo_database.set_model(liststore)
    self.refreshlist(None, self.combo_database, self.combo_database_label,
        self.db_progressbar, '127.0.0.1', 8070)
    self.event_show_button_ok(self.dialog, None)
    return _DBBackupDrop_run(self, parent)

DBBackupDrop.run = DBBackupDrop_run

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

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

DBRestore.run = DBRestore_run

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

def DBLogin_run(self, parent):
    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('127.0.0.1', '8070')
    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('127.0.0.1', 8070)
            dbname = dia.run(self.dialog)
            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(), '127.0.0.1', 8070, db_name)

    if res != gtk.RESPONSE_OK:
        parent.present()
        self.dialog.destroy()
        rpc.logout()
        from tryton.gui.main import Main
        raise Exception('QueryCanceled')
    parent.present()
    self.dialog.destroy()
    return result

DBLogin.run = DBLogin_run

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