class Data(BaseMetadata):
    """ """
    name = 'idsvc.data'

    def __init__(self, *args, **kwargs):
        """
        Required Parameter:
            api_client      # AgavePy client
        Optional Parameters:
            uuid            # unique identifier for existing metadata object
            body            # information held in metadata 'value' field
            meta            # json or dictionary, values may include:
                            #   uuid, owner, schemaId, internalUsername,
                            #   associationIds, lastUpdated, name, value,
                            #   created, _links
        Explicit parameters take precedence over values found in the meta dictionary
        """
        super(Data, self).__init__(*args, **kwargs)

        self.system = None
        system_id = kwargs.get('system_id', None)
        path = kwargs.get('path', None)
        sra_id = kwargs.get('sra_id', None)

        if system_id is not None:
            self.system_id = system_id
        else:
            self.system_id = self.value.get('system_id', None)

        if self.system_id is not None:
            self.value.update({'system_id': self.system_id})

        if path is not None:
            self.path = path
        else:
            self.path = self.value.get('path', None)

        if self.path is not None:
            self.value.update({'path': self.path})

        if sra_id is not None:
            self.sra_id = sra_id
        else:
            self.sra_id = self.value.get('sra_id', None)

        if self.sra_id is not None:
            self.value.update({'sra_id': self.sra_id})

    @property
    def title(self):
        ## When is the 'name' get set?
        file_name = self.value.get('name')
        if file_name:
            return file_name
        else:
            return self.sra_id

    @property
    def project(self):
        return next(iter([x for x in self.containers if x.name == 'idsvc.project']), None)

    @property
    def specimen(self):
        return next(iter([x for x in self.containers if x.name == 'idsvc.specimen']), None)

    @property
    def process(self):
        return next(iter([x for x in self.is_input_to + self.is_output_of if x.name == 'idsvc.process']), None)

    @property
    def datasets(self):
        return [x for x in self.containers if x.name == 'idsvc.datasets']

    @property
    def input_to_process(self):
        return [x for x in self.is_input_to if x.name == 'idsvc.process']

    @property
    def output_of_process(self):
        return [x for x in self.is_output_of if x.name == 'idsvc.process']

    def add_project(self, project):
        """ """ 
        self.add_container(project)


    def load_file_info(self):
        if self.system_id is None:
            exception_msg = 'Missing system id, cannot load file info.'
            logger.exception(exception_msg)
            raise Exception(exception_msg)

        if self.path is None:
            exception_msg = 'Missing file path, cannot load file info.'
            logger.exception(exception_msg)
            raise Exception(exception_msg)

        if self.system is None:
            try:
                self.system = System(api_client=self._api_client, system_id=self.system_id)
            except Exception as e:
                exception_msg = 'Unable to access system with system_id=%s.' % self.system_id
                logger.error(exception_msg)
                raise Exception(exception_msg)

        try:
            listing = self.system.listing(self.path)
            file_info = next(iter(listing), None)
        except Exception as e:
            exception_msg = 'The path=%s could not be listed on system=%s. %s' \
                            % (self.path, self.system_id, e)
            logger.error(exception_msg)
            raise Exception(exception_msg)

        try:
            last_mod = file_info['lastModified']
            file_info['lastModified'] = last_mod.strftime('%b %-d %I:%M')
        except:
            warning_msg = 'Listing response does not contain lastModified.'
            logger.warning(warning_msg)

        self.value = file_info

    def _share(self, username, permission):
        """"""
        body=json.dumps({ 'username': username,
                          'permission': permission,
                          'recursive': False })
        self._api_client.files.updatePermissions(
                systemId=self.system_id,
                filePath=self.value['path'],
                body=body )

    def save(self):
        super(Data, self).save()

        if self.path and self.system_id:
            logger.debug('Sharing data with portal user...')
            self._share(username='******', permission='READ')

    def calculate_checksum(self):
        """ """
        name = "checksum"
        app_id = "idsvc_checksum-0.1"
        archive = True

        portal_client = get_portal_api_client()

        if self.sra_id:
            parameters = {'UUID': self.uuid, 'SRA': self.sra_id}
            body = {'name': name, 'appId': app_id, 'parameters': parameters}
        else:
            agave_url = "agave://%s/%s" % (self.system_id, self.path)
            inputs = { 'AGAVE_URL': agave_url }
            parameters = { 'UUID': self.uuid }
            body={'name': name, 'appId': app_id, 'inputs': inputs, 'parameters': parameters, 'archive': archive}

        try:
            self.meta['value'].update(
                 {'checksum': None,
                  'lastChecksumUpdated': None,
                  'checksumConflict': None,
                  'checkStatus': None})
            self.save()
        except Exception as e:
            exception_msg = 'Unable to initiate job. %s' % e
            logger.error(exception_msg)
            raise Exception(exception_msg)

        try:
            logger.debug("Job submission body: %s" % body)

            import pprint
            pprint.pprint(body)

            # response = self._api_client.jobs.submit(body=body)
            response = portal_client.jobs.submit(body=body)

            logger.debug("Job submission response: %s" % response['id'])
        except Exception as e:
            exception_msg = 'Unable to initiate job. %s' % e
            logger.error(exception_msg)
            raise Exception(exception_msg)

        return response

    def delete(self):
        """Delete a data object, and remove relationships to it"""
        if self.uuid is None:
            raise Exception('Cannot delete without UUID.')

        # delete all objects that have this object's uuid in their associationIds
        for container in self.containers:
            logger.debug('removing part (%s): %s - %s, from container (%s): : %s - %s' %
                         (self.name, self.uuid, self.title, container.name, container.uuid, container.title))
            container.remove_part(self)
            container.save()

        logger.debug('deleting %s: %s - %s' % (self.name, self.uuid, self.title))

        try:
            self._api_client.meta.deleteMetadata(uuid=self.uuid)
        except Exception as e:
            logger.debug('Object does not exist, probably previously deleted. Error: %s' % e)

        self.uuid = None