import logging
import os
import sys
import traceback
import logging.config as lc
import shutil
from pkg_resources import resource_filename #@UnresolvedImport
from allensdk.model.biophysical.run_simulate import RunSimulate


class RunSimulateLims(RunSimulate):
    _log = logging.getLogger('allensdk.internal.model.biophysical.run_simulate_lims')

    def __init__(self,
                 input_json, 
                 output_json):
        super(RunSimulateLims, self).__init__(input_json, output_json)

    def generate_manifest_rma(self,
                              neuronal_model_run_id,
                              manifest_path,
                              api_url=None):
        '''
        Note
        ----
        Other necessary files are also written.
        '''
        import json
        from allensdk.internal.api.queries.biophysical_module_api import BiophysicalModuleApi
        from allensdk.internal.api.queries.biophysical_module_reader import BiophysicalModuleReader

        bma = BiophysicalModuleApi(api_url)
        data = bma.get_neuronal_model_runs(neuronal_model_run_id)

        lr = BiophysicalModuleReader()
        lr.read_lims_message(data, 'lims_message.json')

        with open('lims_message.json', 'w') as f:
            f.write(json.dumps(data[0], sort_keys=True, indent=2))

        lr.to_manifest(manifest_path) 

    def generate_manifest_lims(self,
                               lims_data_path,
                               manifest_path):
        '''
        Note
        ----
        Other necessary files are also written.
        '''
        from allensdk.internal.api.queries.biophysical_module_reader import BiophysicalModuleReader

        self.lims_json = lims_data_path

        lr = BiophysicalModuleReader()
        lr.read_lims_file(self.lims_json)
        
        lr.to_manifest(manifest_path)

    def copy_local(self):
        import allensdk.model.biophysical.run_simulate

        self.load_manifest()

        modfile_dir = self.manifest.get_path('MODFILE_DIR')

        if not os.path.exists(modfile_dir):
            os.mkdir(modfile_dir)

        workdir = self.manifest.get_path('WORKDIR')

        if not os.path.exists(workdir):
            os.mkdir(workdir)

        modfiles = [self.manifest.get_path(key) for key,info
                    in self.manifest.path_info.items()
                    if 'format' in info and info['format'] == 'MODFILE']
        
        for from_file in modfiles:             
            RunSimulate._log.debug("copying %s to %s" % (from_file, modfile_dir))
            shutil.copy(from_file, modfile_dir)
        
        shutil.copy(self.manifest.get_path('fit_parameters'),
                    workdir)
        
        shutil.copyfile(self.manifest.get_path('stimulus_path'),
                        self.manifest.get_path('output_path'))
        
        shutil.copy(resource_filename(allensdk.model.biophysical.run_simulate.__name__,
                                      'cell.hoc'),
                    os.curdir)
    
    
def main(command, lims_strategy_json, lims_response_json):
    ''' Entry point for module.
        :param command: select behavior, nrnivmodl or simulate
        :type command: string    
        :param lims_strategy_json: path to json file output from lims.
        :type lims_strategy_json: string
        :param lims_response_json: path to json file returned to lims.
        :type lims_response_json: string
    '''
    rs = RunSimulateLims(lims_strategy_json,
                     lims_response_json)

    RunSimulateLims._log.debug("command: %s" % (command))
    RunSimulateLims._log.debug("lims strategy json: %s" % (lims_strategy_json))
    RunSimulateLims._log.debug("lims upload json: %s" % (lims_response_json))
        
    log_config = resource_filename('allensdk.model.biophysical.run_simulate',
                                    'logging.conf')
    lc.fileConfig(log_config)
    os.environ['LOG_CFG'] = log_config
    
    if 'nrnivmodl' == command:
        rs.nrnivmodl()
    elif 'copy_local' == command:
        rs.copy_local()
    elif 'generate_manifest_rma' == command:
        rs.generate_manifest_rma(input_json, output_json)
    elif 'generate_manifest_lims' == command:
        rs.generate_manifest_lims(input_json, output_json)
    elif 'generate_manifest_lims' == command:
        rs.generate_manifest_lims(input_json, output_json)
    else:
        rs.simulate()


if __name__ == '__main__':
    command, input_json, output_json = sys.argv[-3:]

    try:
        main(command, input_json, output_json)
        RunSimulateLims._log.debug("success")
    except Exception as e:
        RunSimulate._log.error(traceback.format_exc())
        exit(1)
