from utils import getUnquotedHeader, parseEventDate, postRecordingThread, sendEmail

from sqlalchemy import and_, desc
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound

import ldap, logging, traceback, sys, os
from threading import Thread

from ppdi.model import Base, Conference, ConferenceAction, ModeratorPin

class TrackerConference(object):
    """Represents a conference and its members"""
    def __init__(self, last_event, config, Session):
        self.log = logging.getLogger('Conference')
        self.last_event = last_event
        self.Session = Session
        self.config = config
        self.conf_size = getUnquotedHeader(self.last_event, 'Conference-Size')
        self.conf_name = getUnquotedHeader(self.last_event, 'Conference-Name')
        self.conf_profile = getUnquotedHeader(self.last_event, 'Conference-Profile-Name')
        self.conf_uuid = getUnquotedHeader(self.last_event, 'Conference-Unique-ID')
        
        
        try:
            self.owner = self.Session.query(ModeratorPin).get(self.conf_name)
        except Exception, err:
            self.log.critical(traceback.format_exc())
            raise
        if self.owner is None:
            self.log.critical('Error because we could not get owner.')
            raise Exception('Conference owner does not exist')
            
        self.confObj = self.Session.query(Conference).get(getUnquotedHeader(self.last_event, 'Conference-Unique-ID'))
        if self.confObj is None:
            self.log.debug('Conference does not exist, we must create one.')
            

    def addAction(self, e):
        """Create and add a new action to the DB"""
        self.log.debug('Action taken on %s. %s' % (self.conf_name, getUnquotedHeader(e, 'Action')))
        actionObj = ConferenceAction(getUnquotedHeader(e, 'Action'), 
                                    getUnquotedHeader(e, 'Caller-Caller-ID-Name'),
                                    getUnquotedHeader(e, 'Caller-Caller-ID-Number'),
                                    self.conf_size,
                                    getUnquotedHeader(e, 'Member-Type'),
                                    parseEventDate(e),
                                    self.conf_uuid)
        self.confObj.actions.append(actionObj)
        self.Session.add(actionObj)
        
    def add_member(self, e):
        """Add a new member to the conference"""
        self.last_event = e
        self.conf_size = int(getUnquotedHeader(e, 'Conference-Size')) # Adjust the conference size
        if self.confObj is None:
            self.log.info('Creating a new conference for conference id: %s' % self.conf_uuid)
            self.confObj = Conference(self.conf_uuid, parseEventDate(e), unicode(self.conf_name), unicode(self.conf_profile))
            self.owner.conferences.append(self.confObj)
            self.Session.add(self.confObj)
            self.addAction(e)
            self.Session.flush()
            self.log.debug('Conference %s has been created. Assigning the pointer.' % self.conf_name)
            return

        self.addAction(e)
        self.log.debug('Added a new member to conference %s.' % (self.conf_name))
        
    def del_member(self, e):
        """Remove members from the conference"""
        self.last_event = e
        self.conf_size = int(getUnquotedHeader(e, 'Conference-Size')) # Adjust the conference size
        self.addAction(e)
        if self.conf_size == 0:
            self.confObj.ended = parseEventDate(e)
            try:
                self.log.debug("Conference %s has ended. Removing session %s." % (self.conf_name, self.Session))
                self.Session.commit()
            except Exception, e:
                self.Session.rollback()
                self.log.critical('Could not commit to the DB because: %s' % traceback.format_exc())
                raise
    
    def kick_member(self, e):
        self.addAction(e)
        
    def undeaf_member(self, e):
        self.addAction(e)
        
    def deaf_member(self, e):
        self.addAction(e)
        
    def unmute_member(self, e):
        self.addAction(e)
        
    def mute_member(self, e):
        self.addAction(e)
        
    def gain_level(self, e):
        self.addAction(e)
        
    def volume_level(self, e):
        self.addAction(e)
        
    def energy_level(self, e):
        self.addAction(e)
    
    def lock(self, e):
        """Conference was locked"""
        self.addAction(e)
        
    def unlock(self, e):
        """Conference was unlocked"""
        self.addAction(e)
    
    @staticmethod
    def stop_recording(e, config, Session):
        """Process the process of recording being stopped"""
        log = logging.getLogger('Conference')
        
        owner = Session.query(ModeratorPin).get(getUnquotedHeader(e, 'Conference-Name'))
        if owner is None:
            log.critical('Error because we could not get owner.')
            raise Exception('Conference owner does not exist')
        
        confObj = Session.query(Conference).get(getUnquotedHeader(e, 'Conference-Unique-ID'))
        if confObj is None:
            log.info('Creating a new conference for conference id: %s' % getUnquotedHeader(e, 'Conference-Unique-ID'))
            confObj = Conference(getUnquotedHeader(e, 'Conference-Unique-ID'), parseEventDate(e), unicode(getUnquotedHeader(e, 'Conference-Name')), unicode(getUnquotedHeader(e, 'Conference-Profile-Name')))
            owner.conferences.append(confObj)
            Session.add(confObj)
            Session.flush()
            actionObj = ConferenceAction(unicode(getUnquotedHeader(e, 'Action')), 
                                        unicode(getUnquotedHeader(e, 'Caller-Caller-ID-Name')),
                                        unicode(getUnquotedHeader(e, 'Caller-Caller-ID-Number')),
                                        unicode(getUnquotedHeader(e, 'Conference-Size')),
                                        unicode(getUnquotedHeader(e, 'Member-Type')),
                                        parseEventDate(e),
                                        confObj.id)
            confObj.actions.append(actionObj)
            Session.add(actionObj)
            log.debug('Conference %s has been created. Assigning the pointer.' % getUnquotedHeader(e, 'Conference-Name'))
            
        confObj.recording = os.path.join(config.get('mp3', 'store_to'), getUnquotedHeader(e, 'Path').split('/').pop()[:-3] + 'mp3')
        host = unicode(getUnquotedHeader(e, 'FreeSWITCH-IPv4'))
            
        try:
            try:
                t = Thread(target=postRecordingThread, args=(config, getUnquotedHeader(e, 'Path'), confObj, host, owner))
                t.start()
            except:
                log.critical('Could not run thread and commit to database!\n%s' % traceback.format_exc())
                raise
        finally:
            try:
                sendEmail(config, getUnquotedHeader(e, 'Path'), confObj, owner)
                Session.commit()
            except Exception, e:
                log.critical('Could not commit to database!\n%s' % traceback.format_exc())
                Session.rollback()
                raise