#!/usr/bin/env python

# Copyright (C) 2007-2008 Instituto Nokia de Tecnologia. All rights reserved.
# Contact: Renato Chencarek <renato.chencarek@openbossa.org>
#
# This file is part of Canola.
#
# This software, including documentation, is protected by copyright
# controlled by Instituto Nokia de Tecnologia. All rights are reserved.
# Copying, including reproducing, storing, adapting or translating, any
# or all of this material requires the prior written consent of
# Instituto Nokia de Tecnologia. This material also contains
# confidential information which may not be disclosed to others without
# the prior written consent of Instituto Nokia de Tecnologia.

import os
import sys
import ecore
import ecore.evas
import evas
from optparse import OptionParser

import terra.core.log as log
from terra.core.manager import Manager
from terra.core.plugin_prefs import PluginPrefs

pjoin = os.path.join
pexists = os.path.exists
pisfile = os.path.isfile

mger = None
home_path = os.path.expanduser("~")
cnl_base_path = pjoin(home_path, ".canola")
cnl_theme_path = pjoin(cnl_base_path, "theme")
cnl_prefs_path = pjoin(cnl_base_path, "prefs")

default_theme = pjoin(cnl_theme_path, "theme.edj")
default_conf_theme = pjoin(cnl_theme_path, "conf.edj")
default_font_config = pjoin(cnl_base_path, "fonts.conf")
default_config_file = os.getenv("CNL_CONFIG_FILE",
                                pjoin(os.sep, "etc", "canola.conf"))

def acquire_dbus_service_name():
    import dbus
    bus = dbus.SessionBus()
    bo = bus.get_object("org.freedesktop.DBus",
                        "/org/freedesktop/DBus",
                        introspect=False)
    bi = dbus.Interface(bo, "org.freedesktop.DBus")
    try:
        ret = bi.RequestName("org.openbossa.canola", dbus.UInt32(0))
    except Exception, e:
        log.error("error [%s] while acquiring D-Bus service name for Canola, "
                  "exiting ...", e, exc_info=True)
        sys.exit(1)
    else:
        if not ret:
            log.error("unknown error while acquiring D-Bus service name for "
                      "Canola, exiting ...")
            sys.exit(1)

def setup_etk():
    global default_conf_theme
    # XXX: fallback to local theme directory during development
    if not pisfile(default_conf_theme):
        default_conf_theme = "data/etk-themes/default/default.edj"
    import etk
    etk.theme_widget_set_from_path(default_conf_theme)

def setup_dot_canola():
    version = pjoin(cnl_base_path, "version")
    version_check = "2.0"
    version_str = "2.0.0"

    def init_dot_canola():
        os.makedirs(cnl_base_path, 0700)
        open(version, "w").write(version_str)

    def remove_and_init():
        import shutil
        shutil.rmtree(cnl_base_path)
        init_dot_canola()

    if not pexists(cnl_base_path):
        init_dot_canola()
        return

    if not pexists(version): # Canola 1.X
        remove_and_init()
        return

    ver = open(version, "r").readline().strip()
    if not ver.startswith(version_check):  # not Canola 2.0
        remove_and_init()
        return

def check_prefs():
    system_props = mger.get_class("SystemProperties")() # XXX

    if not pexists(cnl_prefs_path):
        os.makedirs(cnl_prefs_path, 0700)

    settings = PluginPrefs("settings")

    default_dirs = system_props.DEFAULT_DIRS
    
    if not settings.get("audio", None):
        settings["audio"] = default_dirs["audio"]
    if not settings.get("photo", None):
        settings["photo"] = default_dirs["photo"]
    if not settings.get("video", None):
        settings["video"] = default_dirs["video"]

    if not settings.get("cover_path", None):
        cover = pjoin(cnl_base_path, "covers")
        settings["cover_path"] = cover

    if not settings.get("download_path", None):
        dd = system_props.download_dirs_get()
        for dpath, _ in dd:
            if not system_props.is_mounted(os.path.dirname(dpath)):
                continue
            settings["download_path"] = dpath
            break
        else:  # if nothing is mounted, just default to first choice
            settings["download_path"] = dd[0][0]

    temp_dir = settings.get("temp_dir", None)

    if temp_dir is None:
        temp_dir = pjoin(cnl_base_path, "tmp")
        settings["temp_dir"] = temp_dir

    if not pexists(temp_dir):
        os.makedirs(temp_dir, 0700)

    settings.save()

def check_themes():
    themes_dir = mger.terra_config.themes_dir
    if not os.path.isabs(themes_dir):
        themes_dir = pjoin(os.getcwd(), themes_dir)

    if not pexists(cnl_theme_path):
        os.makedirs(cnl_theme_path, 0700)

    if not pexists(default_theme):
        if os.path.lexists(default_theme):
            os.unlink(default_theme)
        os.symlink(pjoin(themes_dir, "default.edj"), default_theme)

    if not pexists(default_conf_theme):
        if os.path.lexists(default_conf_theme):
            os.unlink(default_conf_theme)
        os.symlink(pjoin(themes_dir, "conf.edj"), default_conf_theme)



def apply_font_config(path):
    if not pexists(path):
        return
    import edje
    from ConfigParser import ConfigParser
    cp = ConfigParser()
    cp.read(path)
    for text_class in cp.sections():
        font = cp.get(text_class, "font")
        size = cp.getint(text_class, "size")
        edje.text_class_set(text_class, font, size)


def parse_geometry(option, opt, value, parser):
    try:
        w, h = value.split("x")
        w = int(w)
        h = int(h)
    except Exception, e:
        raise optparse.OptionValueError("Invalid format for %s" % option)
    parser.values.geometry = (w, h)


def process_cmdline():
    usage = "usage: %prog [options]"
    op = OptionParser(usage=usage)
    op.add_option("-e", "--engine", type="choice",
                  choices=("x11", "x11-16"), default="x11-16",
                  help=("which display engine to use (x11, x11-16), "
                        "default=%default"))
    op.add_option("-n", "--no-fullscreen", action="store_true",
                  help="do not launch in fullscreen")
    op.add_option("-g", "--geometry", type="string", metavar="WxH",
                  action="callback", callback=parse_geometry,
                  default=(800, 480),
                  help="use given window geometry")
    op.add_option("-F", "--font-config", default=default_font_config,
                  help="Path to font configuration")
    op.add_option("-f", "--fps", type="int", default=50,
                  help="frames per second to use, default=%default")
    op.add_option("-t", "--theme", default=default_theme,
                  help="Path to theme (.edj) to use. Default=%default")
    op.add_option("-v", "--verbose", default=0, action="count",
                  help=("increase verbosity, can be used multiple times. Effect: "
                        "info (-v), debug (-v -v). Interferes with --quiet."))
    op.add_option("-q", "--quiet", default=0, action="count",
                  help=("increase quiet (less verbose), can be used multiple "
                        "times. Effect: error (-q), fatal (-q -q). Interferes "
                        "with --verbose."))
    op.add_option("-p", "--profile", action="store_true",
                  help="run canola with a profiler and output stats")
    op.add_option("-c", "--config", default=default_config_file,
                  action="store", type="string", dest="config_file",
                  help="Path to canola configuration file (default: %default)")

    return op.parse_args()

## Main ;-)

# Handle options and create output window
options, args = process_cmdline()

log_level_default = log.WARNING
log_level = log_level_default + 10 * (options.quiet - options.verbose)
log.setLevel(log_level)

# check and setup .canola for user
setup_dot_canola()

mger = Manager(options.config_file)

check_prefs()
check_themes()

apply_font_config(options.font_config)

if not pisfile(options.theme):
    log.warning("nonexistent theme %s, using default instead" % options.theme)
    options.theme = default_theme

if not pisfile(options.theme):
    raise SystemExit("No theme found.")

if options.engine == "x11":
    f = ecore.evas.SoftwareX11
elif options.engine == "x11-16":
    if ecore.evas.engine_type_supported_get("software_16_x11"):
        f = ecore.evas.SoftwareX11_16
    else:
        log.warning("x11-16 is not supported, falling back to x11")
        f = ecore.evas.SoftwareX11

w, h = options.geometry
ee = f(w=w, h=h)
ee.fullscreen = not options.no_fullscreen
ecore.animator_frametime_set(1.0 / options.fps)

if options.profile:
    import hotshot, hotshot.stats
    prof = hotshot.Profile("canola.prof")
    prof.start()

# Load and setup UI
ee.title = "Canola"
ee.name_class = ("Canola", "Canola")
ee.evas.font_hinting_set(evas.EVAS_FONT_HINTING_AUTO)

bg = ee.evas.Rectangle(color=(0, 0, 0, 255))
bg.size = ee.evas.size
bg.show()
ee.data["bg"] = bg

MainController = mger.get_class("MainController")
if MainController is None:
    log.error("no plugin for main controller, exiting ...")
    sys.exit(1)

# start everything ;-)
mc = MainController(ee, os.path.realpath(options.theme))
mc.view.size = ee.evas.size
mc.view.show()
ee.data["canola"] = mc.view

def resize_cb(ee):
    ee.data["bg"].size = ee.evas.size
    ee.data["canola"].size = ee.evas.size
ee.callback_resize = resize_cb


def post_show_setup():
    acquire_dbus_service_name()
    setup_etk()
    return False
ecore.timer_add(0.1, post_show_setup)

ee.show()
ecore.main_loop_begin()
mc.cleanup()

if options.profile:
    prof.stop()
    stats = hotshot.stats.load("canola.prof")
    stats.strip_dirs()
    stats.sort_stats("cumulative", "time", "calls")
    stats.print_stats()
