# loemu - A user friendly frontend for game emulators
# 
# Copyright (C) 2008 Bernat Pegueroles Forcadell
# 
# Author: Bernat Pegueroles Forcadell <bernat@pegueroles.cat>
# 
# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


import re
import os
import sys
from ConfigParser import ConfigParser
from glob import glob
from os.path import basename,dirname,isdir,join
from xml.dom.minidom import parse

class FileConfig(ConfigParser):
    def __init__(self):
        ConfigParser.__init__(self)
        self.tag_rx=re.compile("@\(['\"]{1}(?P<section>[^(]+)['\"]{1},['\"]{1}(?P<option>[^(]+)['\"]{1}\)")
        return

    def get(self,section,option):
        try:
            string=re.sub(  self.tag_rx,
                            lambda x: repr(self.get(x.group('section'),x.group('option'))),
                            ConfigParser.get(self,section,option))
        except:
            return None
        try:
            return eval(string)
        except:
            return string

class Configuration(FileConfig):
    def __init__(self):
        FileConfig.__init__(self)
        self.app_name="loemu"
        self.app_version="0.3.1"

        self.emulator= dict()
        self.dirs=dict()
        # XXX platform dependency
        self.dirs['home']= os.environ['HOME'] + "/.loemu"
        self.dirs['config']= sys.prefix + "/share/loemu/config"
        self.dirs['glade'] = sys.prefix + "/share/loemu/glade"
        self.dirs['images'] = sys.prefix + "/share/loemu/images"
        self.dirs['locale'] = sys.prefix + "/share/locale"
        return

    def set_dirs(self,dirs):
        self.dirs.update(dirs)
        return

    def set_dir(self,key,dir):
        self.dirs[key]=dir
        return

    def get_dirs(self):
        return self.dirs

    def get_dir(self,key):
        return self.dirs.get(key,None)

    def load(self):
        if not self.read(join(self.dirs['config'],"general")):
            return _("Can not access to %s file") % join(self.dirs['config'],"general")

        self.emulator=dict()
        self.titles={   'bad':_("Bad"),
                        'best available':_("Best Available"),
                        'good':_("Good"),
                        'unknown':_("Unknown"),
                        'time':_("Played Time"),
                        'exec':_("Executions"),
                        'last':_("Last Played"),
                        'favorite':_("Favorite"),
                    }
        self.keys=dict()
        for key,title in self.titles.iteritems():
            self.keys[title]=key
        self.generic_fields=set(['emulator','state'])
        for file in glob(join(self.dirs['config'],"*.conf")):
            emu = FileConfig()
            if not emu.read(file):
                return _("Can not access to %s file") % file
            self.emulator[emu.get("General","label")]=emu

            for section in emu.get("General","sources"):
                format = emu.get(section,"format")
                if format == "ini-sections":
                    self.generic_fields.update(emu.get(section,"sections").values())
                elif format == "ini-options":
                    self.generic_fields.update(emu.get(section,"options").values())
                elif format == "xml":
                    xslfile=join(self.dirs['config'], emu.get(section,"xsl"))
                    if not os.access(xslfile,os.R_OK):
                        return _("Can not access to %s file") % xslfile
                    dom = parse(xslfile)
                    for element in dom.getElementsByTagName("game"):
                        for i in range(element.attributes.length):
                            self.generic_fields.add(element.attributes.item(i).name)
                elif format == "plain":
                    rx=re.compile(emu.get(section,"pattern"))
                    self.generic_fields.update(rx.groupindex.keys())
                else:
                    return _("Format of source unknown") + " ['xml','ini-sections','ini-options','plain']: " + format

            for key,value in emu.get("General","titles").iteritems():
                self.keys[_(value)]=key
                self.titles[key]=_(value)

        self.fields=set(['time','exec','last','favorite'])
        self.fields.update(self.generic_fields)

        homefile=join(self.dirs['home'],"loemurc")
        self.home_parser=FileConfig()
        if not os.access(homefile,os.R_OK):
            self.write_configuration()
        self.home_parser.read(homefile)
        
        for option,value in self.home_parser.items("General"):
            self.set("General",option,value)
        # Migration from 0.2.0
        if isdir(self.get("General","gamelist")):
            self.set("General","gamelist",self.get("General","gamelist")+"/gamelist.xml")
        for label,parser in self.emulator.iteritems():
            if "Variables" not in parser.sections():
                parser.add_section("Variables")
            for variable in parser.get("General","variables"):
                parser.set("Variables",variable,"")
                if parser.has_option(variable,"default"):
                    default= parser.get(variable,"default")
                    parser.set("Variables",variable,str(default))
                if self.home_parser.has_option(label,variable):
                    value= ConfigParser.get(self.home_parser,label,variable)
                    parser.set("Variables",variable,str(value))

        # save 0.3.0 bug, bad written params are ignored
        for param in ["show","columns","filters","finders"]:
            self.set("General",param,str(filter(lambda x:x in self.fields,self.get("General",param))))
        return

    def write_configuration(self):
        if not os.access(os.environ['HOME'],os.W_OK):
            return _("Can not write to %s file") % join(self.dirs['home'],"loemurc")
        
        if "General" not in self.home_parser.sections():
            self.home_parser.add_section("General")
        for option in self.options("General"):
            value = self.get("General",option)
            self.home_parser.set("General",option,value)

        for label,parser in self.emulator.iteritems():
            if label not in self.home_parser.sections():
                self.home_parser.add_section(label)
            for variable in parser.get("General","variables"):
                self.home_parser.set(label,variable,"")
                if parser.has_option(variable,"default"):
                    default= parser.get(variable,"default")
                    self.home_parser.set(label,variable,default)
                if parser.has_option("Variables",variable):
                    value = parser.get("Variables",variable)
                    self.home_parser.set(label,variable,value)

        if not os.path.isdir(self.dirs['home']):
            os.makedirs(self.dirs['home'])

        fo=file(join(self.dirs['home'],"loemurc"),"w")
        self.home_parser.write(fo)
        fo.close()
        return

    def get_key(self,title):
        return self.keys.get(title,title)

    def get_title(self,key):
        return self.titles.get(key,key)

    def emu(self,id):
        return self.emulator[id]

    def emulators(self):
        return sorted(self.emulator.keys())

config=Configuration()
