# -*- coding: utf-8 -*-
#
# «core» - Abstract lirc creator
#
# Copyright (C) 2010, John Baab, for Mythbuntu
# Copyright (C) 2007-2008, Mario Limonciello, for Mythbuntu
# Copyright (C) 2007, Nick Fox, for Mythbuntu
#
#
# Mythbuntu 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 3 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 application; if not, write to the Free Software Foundation, Inc., 51
# Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
##################################################################################

import os
import re
import string

class ProgramHandler():
    button_dictionary= { \
        "power":"^power|^on_off|^esc|^halt|^off", \
        "clear":"^clear", \
        "up":"^up|^arrow_up|^up_arrow|^arrowup", \
        "down":"^down|^down_arrow|^arrow_down|^arrowdown", \
        "left":"^left|^leftarrow|^seek\-|^right_arrow_term|^arrow_left|^arrowleft|^skipback", \
        "right":"^right|^rightarrow|^seek\+|^left_arrow_term|^arrow_right|^arrowright|^skipfwd", \
        "enter":"^enter|^ent|^start", \
        "rewind":"^rewind|^fastrwd|^rev|^backward|^rrev|^rwnd|^rrew|^grew|^skipr|^skipprior", \
        "forward":"^forward|^fastfwd|^fwd|^fforward|^ffwd|^ff|^rff|^gff|^ffw|^fwdwind|^jump|^skipf|^skipnext|^fastforward", \
        "vol-":"^vol\-|^voldown|^vol-down|^volume\-|^vol_down|^volumedown|^RVolumeDown|^Volume_Minus|^Vol_Minus", \
        "vol+":"^vol\+|^volup|^vol-up|^volume\+|^vol_up|^volumeup|^RVolumeUp|^Volume_Plus|^Vol_Plus", \
        "mute":"^mute|^rmute|^gmute", \
        "chan-":"^chan\-|^chandown|^chan-down|^channel\-|^ch\-|^chdown|^ch_down|^channeldown|^chnldn|^channel_down|^tune\-|^RChannelDown|^Channel_Minus|^Chan_Minus|^PG_DN|^pg\-", \
        "chan+":"^chan\+|^chanup|^chan-up|^channel\+|^ch\+|^chup|^ch_up|^channelup|^chnlup|^channel_up|^tune\+|^RChannelUp|^Channel_Plus|^Chan_Plus|^PG_UP|^pg\+", \
        "ok":"^ok|^start|^ent|^go|^select", \
        "home":"^home", \
        "menu":"^menu|^rmenu|^gmenu|^dvdmenu", \
        "info":"^info|^more|^osd|^display|^preview|^TaskSwitcher", \
        "pause":"^pause|^freeze|^playpause|^play-pause|^play_pause|^still", \
        "play":"^play|playpause|^play-pause|^play_pause", \
        "stop":"^stop|^esc|^cancel|^return", \
        "exit":"^exit|^return|^close|^halt|^back/exit|^backexit|^back", \
        "record":"^record|^rec|^capture", \
        "one":"^1|^one|^r1|^G1", \
        "two":"^2|^two|^r2|^G2", \
        "three":"^3|^three|^r3|^G3", \
        "four":"^4|^four|^r4|^G4", \
        "five":"^5|^five|^r5|^G5", \
        "six":"^6|^six|^r6|^G6", \
        "seven":"^7|^seven|^r7|^G7", \
        "eight":"^8|^eight|^r8|^G8", \
        "nine":"^9|^nine|^r9|^G9", \
        "zero":"^0|^zero|^r0|^G0", \
        "skip":"^skip|^next", \
        "replay":"^replay|^previous|^again", \
        "guide":"^guide|^AppLauncher|^directory", \
        "dvd":"^dvd|^dvd_vcd|^powerdvd|^power_dvd", \
        "red":"^red", \
        "green":"^green", \
        "yellow":"^yellow", \
        "blue":"^blue", \
        "aspect":"^Zoom" , \
        "fullscreen":"^FullScreen", \
        "tuner":"^tuner|^bookmarks", \
        "delete":"^delete|^Hash", \
        "subtitle":"^subtitle"
    }

    def __init__(self,application_name= None, application_dictionary=None,lircd="/etc/lirc/lircd.conf", lircrc=".lircrc", repeat="0", delay="0"):
        if application_name == None or application_dictionary == None:
            self.valid=False
        else:
            self.valid=True
        self.application_name = application_name
        self.application_dictionary = application_dictionary
        self.lircd = lircd
        self.lircrc = lircrc
        self.repeat = repeat
        self.delay = delay

    def is_valid(self):
        return self.valid

    def generate(self):
        """Generates a config for this program type"""
        def parse_lircd(file):
            """Reads in a lircd.conf and returns all buttons found"""
            if re.compile('^"').search(file):
                file=string.split(file,'"')[1]
            if not os.path.exists(file):
                print "WARNING: File " + file + " doesn't exist"
                return {}
            try:
                in_f=open(file).readlines()
            except IOError:
                return {}
            filterpattern = re.compile("^#")
            remotes = {}
            codes=False
            remotename=""
            for line in in_f:
                if filterpattern.search(line) is None:
                    if re.compile("^include").search(line) is not None:
                        sub_remotes = parse_lircd(string.split(line)[1])
                        for remotename,codes in sub_remotes.iteritems():
                            remotes[remotename]=codes
                    if not codes:
                        if re.compile("name").search(line) is not None:
                            list = string.split(line)
                            if len(list) >1 :
                                remotename=list[1]
                        if re.compile("begin codes|begin raw_codes").search(line) is not None:
                            codes=True
                            if not remotes.has_key(remotename):
                                remotes[remotename]=[]
                    else:
                        if re.compile("end codes|end raw_codes").search(line) is not None:
                            codes=False
                        else:
                            list = string.split(line)
                            if len(list) > 1:
                                if list[0] == "name":
                                    remotes[remotename].append(list[1])
                                else:
                                    remotes[remotename].append(list[0])
            return remotes
        self.remotes = parse_lircd(self.lircd)
        out_f = open(self.lircrc,'a')
        out_f.write("# LIRCRC Auto Generated by Mythbuntu Lirc Generator\n# Author(s): Mario Limonciello, Nick Fox, John Baab\n# Created for use with Mythbuntu\n")
        self.match_dictionary(out_f)
        out_f.close()

    def get_app_functionality(self):
        """Returns all required functionality keys"""
        return self.application_dictionary

    def get_app_buttons(self):
        """Returns all mapping created"""
        return self.button_dictionary

    def get_remotes(self):
        """Returns all parsed remotes"""
        return self.remotes

    def debug(self):
        """Outputs a plethora of useful debug info"""
        print "---" + self.application_name + "---"
        print "Parsed Remotes:"
        print self.get_remotes()
        print "App Functionality:"
        print self.get_app_functionality()
        print "Mapped Buttons:"
        print self.get_app_buttons()

    def match_dictionary(self,stream):
        #Go through all possible remotes
        #Remotes are represented as a dictionary item that matches a list
        for remote in self.remotes:
            for button in self.remotes[remote]:
                key_split=button.split('KEY_')
                for item in self.application_dictionary:
                    buttons = item.split(',')
                    pattern = re.compile(self.button_dictionary[buttons[0]],re.IGNORECASE)
                    if pattern.search(button) is not None or \
                       (len(key_split) > 1 and pattern.search(key_split[1])):
                        if len(buttons) == 1:
                            self.write_key(stream,self.application_dictionary[item],button,remote)
                        else:
                            for extrabutton in self.remotes[remote]:
                                extrakey_split=extrabutton.split('KEY_')
                                pattern = re.compile(self.button_dictionary[buttons[1]],re.IGNORECASE)
                                if pattern.search(extrabutton) is not None or \
                                   (len(extrakey_split) > 1 and pattern.search(extrakey_split[1])):
                                    self.write_key(stream,self.application_dictionary[item],button,remote,extrabutton)
                        break #we only want the first instance (ignore _DOWN or _UP)

    def write_key(self,stream,function,button,remote,extrabutton=None):
    	"""Writes a key block"""
    	stream.write("begin\n")
        stream.write("    remote = " + remote +                "\n")
        stream.write("    prog = "   + self.application_name + "\n")
        stream.write("    button = " + button +                "\n")
        if extrabutton is not None:
            stream.write("    button = " + extrabutton +               "\n")
        stream.write("    config = " + function +              "\n")
        stream.write("    repeat = " + self.repeat +           "\n")
        stream.write("    delay = " + self.delay +             "\n")
        stream.write("end\n")
        stream.write("\n")
