# STA experiments
#
# Copyright (C) 2010-2012 Huang Xin
# 
# See LICENSE.TXT that came with this file.
import os
import sys
import time
import Pyro
import subprocess
from Experiment import ExperimentConfig,Experiment

class STAExperiment(Experiment):
    STA_SERVER_PROCESS = None
    STA_SERVER_PORT = 6878
    def __init__(self,*args,**kwargs):
        super(STAExperiment, self).__init__(*args,**kwargs)
        self.pyro_source = ''
        self.exp_param = ''
    def sta_analysis(self, sta_type=None):
        # Beware that the pyro operation is asynchronized. It takes several 
        # hundred millseconds for the app to complete action. So it's safe to wait for
        # remote app taking effect before another pyro operation.
        try:
            self.sta_server = self.get_sta_server()
        except Exception,e:
            self.logger.error('Failed to get sta app. ' + str(e))
        
        try:
            self.logger.info('Starting sta data.')
            self.sta_server.start_data()
        except Exception,e:
            self.logger.error('Failed to start sta app. ' + str(e))
        
        try:
            self.logger.info('Setting up sta app before stimulation.')
            self.pre_stim_setup()
        except Exception,e:
            self.logger.error('Failed to setup sta app. ' + str(e))
        
        try:
            self.wait_for_stim()
        except Exception,e:
            self.logger.error('Failed to wait for stimulation. ' + str(e))
        
        try:
            self.logger.info('Setting up sta app after stimulation.')
            self.post_stim_setup()
        except Exception,e:
            self.logger.error('Failed to setup sta app. ' + str(e))
        
        try:
            data = self.sta_server.get_data()
        except Exception,e:
            self.logger.error('Failed to get data from sta. ' + str(e))
        
        try:
            self.log_sta_data(data)
        except Exception,e:
            self.logger.error('Failed to log sta data. ' + str(e))
        
        try:
            results = self.extract_results(data)
        except Exception,e:
            self.logger.error('Failed to extract sta data. ' + str(e))
            
        try:
            # wait for complete of preceding pyro operationsg
            time.sleep(3.0)
            self.logger.info('Stopping sta data.')
            self.sta_server.stop_data()
        except Exception,e:
            self.logger.error('Failed to stop sta app. ' + str(e))
        
        try:
            # wait for complete of preceding pyro operationsg
            time.sleep(3.0)
            self.logger.info('Closing sta server.')
            self.sta_server.close()
        except Exception,e:
            self.logger.error('Failed to close sta server. ' + str(e))
        
        try:
            return results
        except Exception,e:
            self.logger.error('Failed to return sta result. ' + str(e))
    
    def log_sta_data(self, data):
        pass
    
    def get_sta_server(self):
        self.logger.info('Fetching sta server.')
        try:
            if STAExperiment.STA_SERVER_PROCESS.poll() is not None:
                self.logger.info('STA server is dead.')
                raise
        except:
            self.logger.info('Creating new sta app.')
            sta_app_path = os.path.dirname(__file__) + os.path.sep + 'app' + os.path.sep + self.pyro_source
            args = [sys.executable, sta_app_path, str(STAExperiment.STA_SERVER_PORT)]
            STAExperiment.STA_SERVER_PROCESS = subprocess.Popen(args)
            time.sleep(3.0)
        else:
            self.logger.info('Psth app has been launched.')
        assert STAExperiment.STA_SERVER_PROCESS.poll() is None
        URI = "PYROLOC://localhost:%d/%s" % (STAExperiment.STA_SERVER_PORT, 'sta_server')
        Pyro.core.initClient()
        return Pyro.core.getProxyForURI(URI)
    
    def pre_stim_setup(self):
        self.sta_server.set_title(self.exp_name)
        
    def post_stim_setup(self):
        pass
    
    def extract_results(self, _data):
        raise RuntimeError("Must override extract_results method with exp implementation!")