<commit_before>'use strict';

import React from 'react';
import PropTypes from 'prop-types';
import url from 'url';
import _ from 'underscore';
import memoize from 'memoize-one';
import moment from 'moment';
import { Modal, Button } from 'react-bootstrap';
import { Schemas, DateUtility, ajax, JWT, typedefs } from './../../../util';
import { uniqueFileCount, fileCountWithDuplicates, uniqueFileCountNonMemoized } from './../SelectedFilesController';


// eslint-disable-next-line no-unused-vars
const { Item } = typedefs;


/**
 * BrowseView allows to filter down by filetype so we receive a selectedFiles and a subSelectedFiles.
 * This may likely change in future.
 */
export const BrowseViewSelectedFilesDownloadButton = React.memo(function BrowseViewSelectedFilesDownloadButton(props){
    const { selectedFiles, subSelectedFiles } = props;
    const selectedFilesUniqueCount = uniqueFileCount(selectedFiles);
    const selectedFilesCountIncludingDuplicates = fileCountWithDuplicates(selectedFiles);
    const subSelectedFilesCountUnique = subSelectedUniqueFileCount(subSelectedFiles);
    const subSelectedFilesCountIncludingDuplicates = subSelectedFileCountWithDuplicates(subSelectedFiles);
    const disabled = selectedFilesUniqueCount === 0;

    let countDuplicates = selectedFilesCountIncludingDuplicates - selectedFilesUniqueCount;
    let countToShow = selectedFilesUniqueCount; // Unique count would align to quick info bar count better.
    let tooltip = (
        "Download metadata TSV sheet containing download URIs for " +
        selectedFilesUniqueCount + " files" +
        (countDuplicates ? " ( + " + countDuplicates + " non-counted duplicate" + (countDuplicates > 1 ? 's' : '') + ")." : '')
    );

    if (subSelectedFilesCountUnique && subSelectedFilesCountUnique !== selectedFilesUniqueCount){
        countDuplicates = subSelectedFilesCountIncludingDuplicates - subSelectedFilesCountUnique;
        countToShow = subSelectedFilesCountUnique;
        tooltip = (
            subSelectedFilesCountUnique + " selected files filtered in out of " +
            selectedFilesUniqueCount + " total" +
            (countDuplicates? " ( + " + countDuplicates + " non-counted duplicate" + (countDuplicates > 1 ? 's' : '') + ")." : '')
        );
    }

    return (
        <SelectedFilesDownloadButton selectedFiles={subSelectedFiles || selectedFiles} filenamePrefix="metadata_"
            id="browse-view-download-files-btn" data-tip={tooltip} disabled={disabled} className={disabled ? 'btn-secondary' : 'btn-primary'}>
            <i className="icon icon-download icon-fw shift-down-1 mr-07"/>
            <span className="hidden-xs hidden-sm">Download </span>
            <span className="count-to-download-integer">{ countToShow }</span>
            <span className="hidden-xs hidden-sm text-400"> Selected Files</span>
        </SelectedFilesDownloadButton>
    );
});

/**
 * Exact same functionality as `fileCountWithDuplicates`, however memoized for
 * usage with `subSelectedFiles` instead of `selectedFiles`.
 */
const subSelectedFileCountWithDuplicates = memoize(function(subSelectedFiles){
    return _.keys(subSelectedFiles).length;
});
const subSelectedUniqueFileCount = memoize(uniqueFileCountNonMemoized);




/**
 * Upon clicking the button, reveal a modal popup giving users more download instructions.
 */
export class SelectedFilesDownloadButton extends React.PureComponent {

    static propTypes = {
        'windowWidth' : PropTypes.number.isRequired,
        'id' : PropTypes.string,
        'selectedFiles' : PropTypes.object.isRequired,
        'filenamePrefix' : PropTypes.string.isRequired
    };

    static defaultProps = {
        'id' : null,
        'filenamePrefix' : "metadata_",
        'children' : "Download",
        'className' : 'btn-primary'
    };

    constructor(props){
        super(props);
        _.bindAll(this, 'hideModal', 'showModal');
        this.state = { 'modalOpen' : false };
    }

    hideModal(){
        this.setState({ 'modalOpen' : false });
    }

    showModal(){
        this.setState({ 'modalOpen' : true });
    }

    render(){
        const { selectedFiles, filenamePrefix, children, disabled } = this.props;
        const { modalOpen } = this.state;
        const btnProps = _.omit(this.props, 'filenamePrefix', 'selectedFiles', 'windowWidth', 'children', 'disabled');
        // There might be multiple buttons in a view (e.g. ExperimentSetView)
        // so ideally will calculate `props.disabled` rather than use the memoized
        // fileCountWithDuplicates here
        const isDisabled = disabled || fileCountWithDuplicates(selectedFiles) === 0;
        return (
            <React.Fragment>
                <Button {...btnProps} disabled={isDisabled} onClick={this.showModal}>
                    { children }
                </Button>
                { modalOpen ?
                    <SelectedFilesDownloadModal {...{ selectedFiles, filenamePrefix }} onHide={this.hideModal}/>
                    : null }
            </React.Fragment>
        );
    }
}



class SelectedFilesDownloadModal extends React.PureComponent {

    static findUnpublishedFiles = memoize(function(selectedFiles){
        return _.any(_.values(selectedFiles || {}), function(file){
            return !(
                (file.from_experiment && file.from_experiment.from_experiment_set && file.from_experiment.from_experiment_set.produced_in_pub)
                || (file.from_experiment_set && file.from_experiment_set.produced_in_pub)
            );
        });
    });

    constructor(props){
        super(props);
        this.handleAcceptDisclaimer = this.handleAcceptDisclaimer.bind(this);
        this.state = {
            'disclaimerAccepted' : false
        };
    }

    handleAcceptDisclaimer(){
        this.setState({ 'disclaimerAccepted' : true });
    }

    render(){
        const { onHide, filenamePrefix, selectedFiles } = this.props;
        const { disclaimerAccepted } = this.state;

        const suggestedFilename = filenamePrefix + DateUtility.display(moment().utc(), 'date-time-file', '-', false) + '.tsv';
        const userInfo = JWT.getUserInfo();
        const isSignedIn = !!(userInfo && userInfo.details && userInfo.details.email && userInfo.id_token);
        const profileHref = (isSignedIn && userInfo.user_actions && _.findWhere(userInfo.user_actions, { 'id' : 'profile' }).href) || '/me';
        const countSelectedFiles = fileCountWithDuplicates(selectedFiles);
        const foundUnpublishedFiles = SelectedFilesDownloadModal.findUnpublishedFiles(selectedFiles);

        return (
            <Modal show className="batch-files-download-modal" onHide={onHide} bsSize="large">

                <Modal.Header closeButton>
                    <Modal.Title>
                        <span className="text-400">Download <span className="text-600">{ countSelectedFiles }</span> Files</span>
                    </Modal.Title>
                </Modal.Header>

                <Modal.Body>

                    <p>Please press the &quot;Download&quot; button below to save the metadata TSV file which contains download URLs and other information for the selected files.</p>
                    <p>Once you have saved the metadata TSV, you may download the files on any machine or server with the following cURL command:</p><commit_msg>Download modal filecount<commit_after>'use strict';

import React from 'react';
import PropTypes from 'prop-types';
import url from 'url';
import _ from 'underscore';
import memoize from 'memoize-one';
import moment from 'moment';
import { Modal, Button } from 'react-bootstrap';
import { Schemas, DateUtility, ajax, JWT, typedefs } from './../../../util';
import { uniqueFileCount, fileCountWithDuplicates, uniqueFileCountNonMemoized } from './../SelectedFilesController';


// eslint-disable-next-line no-unused-vars
const { Item } = typedefs;


/**
 * BrowseView allows to filter down by filetype so we receive a selectedFiles and a subSelectedFiles.
 * This may likely change in future.
 */
export const BrowseViewSelectedFilesDownloadButton = React.memo(function BrowseViewSelectedFilesDownloadButton(props){
    const { selectedFiles, subSelectedFiles } = props;
    const selectedFilesUniqueCount = uniqueFileCount(selectedFiles);
    const selectedFilesCountIncludingDuplicates = fileCountWithDuplicates(selectedFiles);
    const subSelectedFilesCountUnique = subSelectedUniqueFileCount(subSelectedFiles);
    const subSelectedFilesCountIncludingDuplicates = subSelectedFileCountWithDuplicates(subSelectedFiles);
    const disabled = selectedFilesUniqueCount === 0;

    let countDuplicates = selectedFilesCountIncludingDuplicates - selectedFilesUniqueCount;
    let countToShow = selectedFilesUniqueCount; // Unique count would align to quick info bar count better.
    let tooltip = (
        "Download metadata TSV sheet containing download URIs for " +
        selectedFilesUniqueCount + " files" +
        (countDuplicates ? " ( + " + countDuplicates + " non-counted duplicate" + (countDuplicates > 1 ? 's' : '') + ")." : '')
    );

    if (subSelectedFilesCountUnique && subSelectedFilesCountUnique !== selectedFilesUniqueCount){
        countDuplicates = subSelectedFilesCountIncludingDuplicates - subSelectedFilesCountUnique;
        countToShow = subSelectedFilesCountUnique;
        tooltip = (
            subSelectedFilesCountUnique + " selected files filtered in out of " +
            selectedFilesUniqueCount + " total" +
            (countDuplicates? " ( + " + countDuplicates + " non-counted duplicate" + (countDuplicates > 1 ? 's' : '') + ")." : '')
        );
    }

    return (
        <SelectedFilesDownloadButton selectedFiles={subSelectedFiles || selectedFiles} filenamePrefix="metadata_"
            id="browse-view-download-files-btn" data-tip={tooltip} disabled={disabled} className={disabled ? 'btn-secondary' : 'btn-primary'}>
            <i className="icon icon-download icon-fw shift-down-1 mr-07"/>
            <span className="hidden-xs hidden-sm">Download </span>
            <span className="count-to-download-integer">{ countToShow }</span>
            <span className="hidden-xs hidden-sm text-400"> Selected Files</span>
        </SelectedFilesDownloadButton>
    );
});

/**
 * Exact same functionality as `fileCountWithDuplicates`, however memoized for
 * usage with `subSelectedFiles` instead of `selectedFiles`.
 */
const subSelectedFileCountWithDuplicates = memoize(function(subSelectedFiles){
    return _.keys(subSelectedFiles).length;
});
const subSelectedUniqueFileCount = memoize(uniqueFileCountNonMemoized);




/**
 * Upon clicking the button, reveal a modal popup giving users more download instructions.
 */
export class SelectedFilesDownloadButton extends React.PureComponent {

    static propTypes = {
        'windowWidth' : PropTypes.number.isRequired,
        'id' : PropTypes.string,
        'selectedFiles' : PropTypes.object.isRequired,
        'filenamePrefix' : PropTypes.string.isRequired
    };

    static defaultProps = {
        'id' : null,
        'filenamePrefix' : "metadata_",
        'children' : "Download",
        'className' : 'btn-primary'
    };

    constructor(props){
        super(props);
        _.bindAll(this, 'hideModal', 'showModal');
        this.state = { 'modalOpen' : false };
    }

    hideModal(){
        this.setState({ 'modalOpen' : false });
    }

    showModal(){
        this.setState({ 'modalOpen' : true });
    }

    render(){
        const { selectedFiles, filenamePrefix, children, disabled } = this.props;
        const { modalOpen } = this.state;
        const btnProps = _.omit(this.props, 'filenamePrefix', 'selectedFiles', 'windowWidth', 'children', 'disabled');
        // There might be multiple buttons in a view (e.g. ExperimentSetView)
        // so ideally will calculate `props.disabled` rather than use the memoized
        // fileCountWithDuplicates here
        const isDisabled = disabled || fileCountWithDuplicates(selectedFiles) === 0;
        return (
            <React.Fragment>
                <Button {...btnProps} disabled={isDisabled} onClick={this.showModal}>
                    { children }
                </Button>
                { modalOpen ?
                    <SelectedFilesDownloadModal {...{ selectedFiles, filenamePrefix }} onHide={this.hideModal}/>
                    : null }
            </React.Fragment>
        );
    }
}



class SelectedFilesDownloadModal extends React.PureComponent {

    static findUnpublishedFiles = memoize(function(selectedFiles){
        return _.any(_.values(selectedFiles || {}), function(file){
            return !(
                (file.from_experiment && file.from_experiment.from_experiment_set && file.from_experiment.from_experiment_set.produced_in_pub)
                || (file.from_experiment_set && file.from_experiment_set.produced_in_pub)
            );
        });
    });

    constructor(props){
        super(props);
        this.handleAcceptDisclaimer = this.handleAcceptDisclaimer.bind(this);
        this.state = {
            'disclaimerAccepted' : false
        };
    }

    handleAcceptDisclaimer(){
        this.setState({ 'disclaimerAccepted' : true });
    }

    render(){
        const { onHide, filenamePrefix, selectedFiles } = this.props;
        const { disclaimerAccepted } = this.state;

        const suggestedFilename = filenamePrefix + DateUtility.display(moment().utc(), 'date-time-file', '-', false) + '.tsv';
        const userInfo = JWT.getUserInfo();
        const isSignedIn = !!(userInfo && userInfo.details && userInfo.details.email && userInfo.id_token);
        const profileHref = (isSignedIn && userInfo.user_actions && _.findWhere(userInfo.user_actions, { 'id' : 'profile' }).href) || '/me';
        const countSelectedFilesUnique = uniqueFileCount(selectedFiles);
        const foundUnpublishedFiles = SelectedFilesDownloadModal.findUnpublishedFiles(selectedFiles);

        return (
            <Modal show className="batch-files-download-modal" onHide={onHide} bsSize="large">

                <Modal.Header closeButton>
                    <Modal.Title>
                        <span className="text-400">Download <span className="text-600">{ countSelectedFilesUnique }</span> Files</span>
                    </Modal.Title>
                </Modal.Header>

                <Modal.Body>

                    <p>Please press the &quot;Download&quot; button below to save the metadata TSV file which contains download URLs and other information for the selected files.</p>
                    <p>Once you have saved the metadata TSV, you may download the files on any machine or server with the following cURL command:</p>
{'fraction_non_alphanumeric': 0.1110582478080609, 'fraction_numerical': 0.002174947325494461, 'mean_word_length': 3.019120458891013, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 43, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '424834', 'n_tokens_mistral': 3932, 'n_tokens_neox': 3801, 'n_words': 913}