def view(request, dataset_uuid):
    """View a specific dataset"""
    if request.user.is_anonymous():
        api_client = get_portal_api_client()
    else:
        api_client = request.user.agave_oauth.api_client

    try:
        dataset = Dataset(api_client=api_client, uuid=dataset_uuid)
        project = dataset.project
        data = dataset.data
    except Exception as e:
        exception_msg = 'Unable to load process. %s' % e
        logger.error(exception_msg)
        messages.warning(request, exception_msg)
        return HttpResponseRedirect(reverse('ids_projects:project-list-private'))

    try:
        process_types = get_process_type_keys(project)
        dataset_fields = get_dataset_fields(project)
        dataset.set_fields(dataset_fields)
    except Exception as e:
        exception_msg = 'Unable to load config values. %s' % e
        logger.warning(exception_msg)

    context = { 'project': project,
                'dataset': dataset,
                'datas': data,
                'process_types': process_types }

    return render(request, 'ids_projects/datasets/detail.html', context)
def create(request):
    """Create a new dataset"""

    project_uuid = request.GET.get('project_uuid', None)

    if not project_uuid:
        messages.warning(request, 'Missing project UUID, cannot find processes.')
        return HttpResponseRedirect(reverse('ids_projects:project-list-private'))

    api_client = request.user.agave_oauth.api_client

    try:
        project = Project(api_client=api_client, uuid=project_uuid)
    except Exception as e:
        exception_msg = 'Unable to load project, cannot create dataset. %s' % e
        logger.error(exception_msg)
        messages.warning(request, exception_msg)
        return HttpResponseRedirect(reverse('ids_projects:project-list-private'))

    try:
        dataset_fields = get_dataset_fields(project)
    except Exception as e:
        exception_msg = 'Missing project type information, cannot create dataset. %s' % e
        logger.error(exception_msg)
        messages.warning(request, exception_msg)
        return HttpResponseRedirect(
                    reverse('ids_projects:project-view',
                            kwargs={'project_uuid': project.uuid}))

    context = {'project': project}

    # data_choices = [(x.uuid, x.title) for x in project.data]

    #######
    # GET #
    #######
    if request.method == 'GET':

        # context['form_dataset_create'] = DatasetForm(fields=dataset_fields, choices=data_choices)
        context['form_dataset_create'] = DatasetForm(fields=dataset_fields)
        return render(request, 'ids_projects/datasets/create.html', context)

    ########
    # POST #
    ########
    elif request.method == 'POST':

        #form_dataset = DatasetForm(fields=dataset_fields, choices=data_choices, initial=request.POST)
        form_dataset = DatasetForm(dataset_fields, request.POST)

        if form_dataset.is_valid():
            logger.debug('Dataset form is valid')

            try:

                dataset = Dataset(api_client=api_client, value=form_dataset.cleaned_data)
                dataset.save()

                # create two-way relationship to project
                project.add_part(dataset)
                project.save()

                dataset.add_container(project)
                dataset.save()

                success_msg = 'Successfully created dataset.'
                logger.info(success_msg)
                messages.success(request, success_msg)
                return HttpResponseRedirect(
                            reverse('ids_projects:dataset-view',
                                    kwargs={'dataset_uuid': dataset.uuid}))
            except HTTPError as e:
                exception_msg = 'Unable to create new dataset. %s' % e
                logger.error(exception_msg)
                messages.error(request, exception_msg)
                return HttpResponseRedirect(
                            reverse('ids_projects:project-view',
                                    kwargs={'project_uuid': project.uuid}))

        else:
            exception_msg = "Dataset form is not valid!"
            logger.error(exception_msg)
            messages.error(request, exception_msg)
            return HttpResponseRedirect(
                reverse('ids_projects:project-view',
                        kwargs={'project_uuid': project.uuid}))
def edit(request, dataset_uuid):
    """Edit existing dataset metadata"""
    api_client = request.user.agave_oauth.api_client

    try:
        dataset = Dataset(api_client=api_client, uuid=dataset_uuid)
        project = dataset.project
    except Exception as e:
        exception_msg = 'Unable to edit dataset. %s' % e
        logger.exception(exception_msg)
        messages.warning(request, exception_msg)
        return HttpResponseRedirect('/projects/')

    try:
        dataset_fields = get_dataset_fields(project)
    except Exception as e:
        exception_msg = 'Missing project type information, cannot edit dataset. %s' % e
        logger.error(exception_msg)
        messages.warning(request, exception_msg)
        return HttpResponseRedirect(
            reverse('ids_projects:project-view',
                    kwargs={'project_uuid': project.uuid}))

    # data_choices = [(x.uuid, x.title) for x in project.data]

    #######
    # GET #
    #######
    if request.method == 'GET':

        context = {'form_dataset_edit': DatasetForm(dataset_fields, dataset.value),
                   'dataset': dataset,
                   'project': project}

        return render(request, 'ids_projects/datasets/create.html', context)

    ########
    # POST #
    ########
    elif request.method == 'POST':

        form = DatasetForm(dataset_fields, request.POST)

        if form.is_valid():

            try:
                dataset.value.update(form.cleaned_data)
                dataset.save()

                messages.info(request, 'Dataset successfully edited.')
                return HttpResponseRedirect(
                    reverse('ids_projects:dataset-view',
                            kwargs={'dataset_uuid': dataset.uuid}))
            except Exception as e:
                exception_msg = 'Unable to edit dataset. %s' % e
                logger.error(exception_msg)
                messages.error(request, exception_msg)
                return HttpResponseRedirect(
                    reverse('ids_projects:dataset-view',
                            kwargs={'dataset_uuid': dataset.uuid}))

        else:
            exception_msg = "Dataset form is not valid!"
            logger.error(exception_msg)
            messages.error(request, exception_msg)
            return HttpResponseRedirect(
                reverse('ids_projects:dataset-view',
                        kwargs={'dataset_uuid': dataset.uuid}))
def select_data(request, dataset_uuid):
    """List data to add to dataset."""
    api_client = request.user.agave_oauth.api_client

    try:
        dataset = Dataset(api_client=api_client, uuid=dataset_uuid)
        project = dataset.project
        dataset_data = [x.uuid for x in dataset.data]
        project_data = [x.uuid for x in project.data]
    except Exception as e:
        exception_msg = 'Unable to load process. %s' % e
        logger.error(exception_msg)
        messages.warning(request, exception_msg)
        return HttpResponseRedirect(reverse('ids_projects:project-list-private'))

    try:
        process_types = get_process_type_keys(project)
        dataset_fields = get_dataset_fields(project)
        dataset.set_fields(dataset_fields)
    except Exception as e:
        exception_msg = 'Unable to load config values. %s' % e
        logger.warning(exception_msg)

    #######
    # GET #
    #######
    if request.method == 'GET':

        context = {'project': project,
                   'dataset': dataset,
                   'datas': dataset_data,
                   'process_types': process_types}

        return render(request, 'ids_projects/datasets/select_data.html', context)

    ########
    # POST #
    ########
    elif request.method == 'POST':

        # TODO: this is probably not the best way to do this
        body = urllib.unquote(request.body)

        selected_data = []

        if body:
            response_tuples = map(lambda x: (x.split('=')[0], x.split('=')[1]), body.split('&'))
            selected_data = []
            for key, value in response_tuples:
                selected_data.append(value)

        unselected_data = list(set(project_data) - set(selected_data))
        data_to_remove = filter(lambda x: x in dataset_data, unselected_data)
        data_to_add = list(set(selected_data) - set(dataset_data))

        # remove unselected data
        try:
            if data_to_remove:
                for data_uuid in data_to_remove:
                    data = Data(api_client=api_client, uuid=data_uuid)

                    logger.debug('removing: "%s" from dataset: "%s"' % (data.name, dataset.title))

                    data.remove_container(dataset)
                    data.save()
                    dataset.remove_part(data)

                dataset.save()
        except HTTPError as e:
            exception_msg = 'Unable to remove data from dataset. %s' % e
            logger.error(exception_msg)
            messages.error(request, exception_msg)
            return HttpResponseRedirect(
                reverse('ids_projects:dataset-view',
                        kwargs={'dataset_uuid': dataset.uuid}))

        # add selected data
        try:
            if data_to_add:
                for data_uuid in data_to_add:
                    data = Data(api_client=api_client, uuid=data_uuid)

                    logger.debug('adding: "%s" to dataset: "%s"' % (data.name, dataset.title))

                    data.add_container(dataset)
                    data.save()
                    dataset.add_part(data)

                dataset.save()

            success_msg = 'Successfully added data to dataset.'
            logger.info(success_msg)
            messages.success(request, success_msg)
            return HttpResponseRedirect(reverse('ids_projects:dataset-view', kwargs={'dataset_uuid': dataset.uuid}))

        except HTTPError as e:
            exception_msg = 'Unable to select data. %s' % e
            logger.error(exception_msg)
            messages.error(request, exception_msg)
            return HttpResponseRedirect(
                reverse('ids_projects:dataset-view',
                        kwargs={'dataset_uuid': dataset.uuid}))