'use strict';

import React from 'react';
import Router from 'react-router';

import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import Button from 'react-bootstrap/lib/Button';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';

import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store';
import CoaActions from '../actions/coa_actions';
import CoaStore from '../stores/coa_store';

import MediaPlayer from './ascribe_media/media_player';

import CollapsibleParagraph from './ascribe_collapsible/collapsible_paragraph';

import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property';
import InputTextAreaToggable from './ascribe_forms/input_textarea_toggable';

import PieceExtraDataForm from './ascribe_forms/form_piece_extradata';
import RequestActionForm from './ascribe_forms/form_request_action';

import EditionActions from '../actions/edition_actions';
import AclButtonList from './ascribe_buttons/acl_button_list';

import ReactS3FineUploader from './ascribe_uploader/react_s3_fine_uploader';

import GlobalNotificationModel from '../models/global_notification_model';
import GlobalNotificationActions from '../actions/global_notification_actions';

import apiUrls from '../constants/api_urls';
import AppConstants from '../constants/application_constants';

import { getCookie } from '../utils/fetch_api_utils';

let Link = Router.Link;
/**
 * This is the component that implements display-specific functionality
 */
let Edition = React.createClass({
    propTypes: {
        edition: React.PropTypes.object,
        loadEdition: React.PropTypes.func
    },

    getInitialState() {
        return UserStore.getState();
    },

    componentDidMount() {
        UserStore.listen(this.onChange);
        UserActions.fetchCurrentUser();
    },

    componentWillUnmount() {
        UserStore.unlisten(this.onChange);
    },

    onChange(state) {
        this.setState(state);
    },



    render() {
        let thumbnail = this.props.edition.thumbnail;
        let mimetype = this.props.edition.digital_work.mime;
        let extraData = null;

        if (this.props.edition.digital_work.encoding_urls) {
            extraData = this.props.edition.digital_work.encoding_urls.map(e => { return { url: e.url, type: e.label }; });
        }

        let bitcoinIdValue = (
            <a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.bitcoin_id}>{this.props.edition.bitcoin_id}</a>
        );

        let hashOfArtwork = (
            <a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.hash_as_address}>{this.props.edition.hash_as_address}</a>
        );

        let ownerAddress = (
            <a target="_blank" href={'https://www.blocktrail.com/BTC/address/' + this.props.edition.btc_owner_address_noprefix}>{this.props.edition.btc_owner_address_noprefix}</a>
        );

        return (
            <Row>
                <Col md={6}>
                    <MediaPlayer mimetype={mimetype}
                                    preview={thumbnail}
                                    url={this.props.edition.digital_work.url}
                                    extraData={extraData} />
                    <p className="text-center">
                        <Button bsSize="xsmall" href={this.props.edition.digital_work.url} target="_blank">
                            Download <Glyphicon glyph="cloud-download" />
                        </Button>
                    </p>
                </Col>
                <Col md={6} className="ascribe-edition-details">
                    <EditionHeader edition={this.props.edition}/>
                    <EditionSummary
                        currentUser={this.state.currentUser}
                        edition={this.props.edition} />

                    <CollapsibleParagraph
                        title="Notes"
                        show={(this.state.currentUser.username && true || false) ||
                                (this.props.edition.acl.indexOf('edit') > -1 || this.props.edition.public_note)}>
                        <EditionPersonalNote
                            currentUser={this.state.currentUser}
                            handleSuccess={this.props.loadEdition}
                            edition={this.props.edition}/>
                        <EditionPublicEditionNote
                            handleSuccess={this.props.loadEdition}
                            edition={this.props.edition}/>
                    </CollapsibleParagraph>

                    <CollapsibleParagraph
                        title="Further Details"
                        show={this.props.edition.acl.indexOf('edit') > -1
                            || Object.keys(this.props.edition.extra_data).length > 0
                            || this.props.edition.other_data !== null}>
                        <EditionFurtherDetails
                            handleSuccess={this.props.loadEdition}
                            edition={this.props.edition}/>
                    </CollapsibleParagraph>

                    <CollapsibleParagraph
                        title="Certificate of Authenticity"
                        show={this.props.edition.acl.indexOf('coa') > -1}>
                        <CoaDetails
                            edition={this.props.edition}/>
                    </CollapsibleParagraph>

                    <CollapsibleParagraph
                        title="Provenance/Ownership History"
                        show={this.props.edition.ownership_history && this.props.edition.ownership_history.length > 0}>
                        <EditionDetailHistoryIterator
                            history={this.props.edition.ownership_history} />
                    </CollapsibleParagraph>

                    <CollapsibleParagraph
                        title="Consignment History"
                        show={this.props.edition.consign_history && this.props.edition.consign_history.length > 0}>
                        <EditionDetailHistoryIterator
                            history={this.props.edition.consign_history} />
                    </CollapsibleParagraph>

                    <CollapsibleParagraph
                        title="Loan History"
                        show={this.props.edition.loan_history && this.props.edition.loan_history.length > 0}>
                        <EditionDetailHistoryIterator
                            history={this.props.edition.loan_history} />
                    </CollapsibleParagraph>

                    <CollapsibleParagraph
                        title="SPOOL Details">
                        <Form >
                            <Property
                                name='artwork_id'
                                label="Artwork ID"
                                editable={false}>
                                <pre className="ascribe-pre">{bitcoinIdValue}</pre>
                            </Property>
                            <Property
                                name='hash_of_artwork'
                                label="Hash of Artwork, title, etc"
                                editable={false}>
                                <pre className="ascribe-pre">{hashOfArtwork}</pre>
                            </Property>
                            <Property
                                name='owner_address'
                                label="Owned by SPOOL address"
                                editable={false}>
                                <pre className="ascribe-pre">{ownerAddress}</pre>
                            </Property>
                            <hr />
                        </Form>
                    </CollapsibleParagraph>
                </Col>
            </Row>
        );
    }
});

let EditionHeader = React.createClass({
    propTypes: {
        edition: React.PropTypes.object
    },

    render() {
        var titleHtml = <div className="ascribe-detail-title">{this.props.edition.title}</div>;
        return (
            <div className="ascribe-detail-header">
                <EditionDetailProperty label="TITLE" value={titleHtml} />
                <EditionDetailProperty label="BY" value={this.props.edition.artist_name} />
                <EditionDetailProperty label="DATE" value={ this.props.edition.date_created.slice(0, 4) } />
                <hr/>
            </div>
        );
    }
});


let EditionSummary = React.createClass({
    propTypes: {
        edition: React.PropTypes.object
    },

    getTransferWithdrawData(){
        return {'bitcoin_id': this.props.edition.bitcoin_id};
    },
    handleSuccess(){
        EditionActions.fetchOne(this.props.edition.id);
    },
    showNotification(response){
        this.handleSuccess();
        let notification = new GlobalNotificationModel(response.notification, 'success');
        GlobalNotificationActions.appendGlobalNotification(notification);
    },
    render() {
        let status = null;
        if (this.props.edition.status.length > 0){
            let statusStr = this.props.edition.status.join().replace(/_/, ' ');
            status = <EditionDetailProperty label="STATUS" value={ statusStr }/>;
            if (this.props.edition.pending_new_owner && this.props.edition.acl.indexOf('withdraw_transfer') > -1){
                status = (
                    <Form
                        url={apiUrls.ownership_transfers_withdraw}
                        getFormData={this.getTransferWithdrawData}
                        handleSuccess={this.showNotification}>
                        <EditionDetailProperty label="STATUS" value={ statusStr }>
                            <button
                                type="submit"
                                className="pull-right btn btn-default btn-sm">
                                WITHDRAW
                            </button>
                        </EditionDetailProperty>
                    </Form>
                );
            }
        }
        let actions = null;
        if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
            actions = (
                <RequestActionForm
                    editions={ [this.props.edition] }
                    handleSuccess={this.showNotification}/>);
        }
        else {
            actions = (
                <Row>
                    <Col md={12}>
                        <AclButtonList
                            className="text-center ascribe-button-list"
                            availableAcls={this.props.edition.acl}
                            editions={[this.props.edition]}
                            handleSuccess={this.handleSuccess} />
                    </Col>
                </Row>);
        }

        return (
            <div className="ascribe-detail-header">
                <EditionDetailProperty label="EDITION"
                    value={this.props.edition.edition_number + ' of ' + this.props.edition.num_editions} />
                <EditionDetailProperty label="ID" value={ this.props.edition.bitcoin_id } />
                <EditionDetailProperty label="OWNER" value={ this.props.edition.owner } />
                {status}
                <br/>
                {actions}
                <hr/>
            </div>
        );

    }
});


let EditionDetailProperty = React.createClass({
    propTypes: {
        label: React.PropTypes.string,
        value: React.PropTypes.oneOfType([
            React.PropTypes.string,
            React.PropTypes.element
        ]),
        separator: React.PropTypes.string,
        labelClassName: React.PropTypes.string,
        valueClassName: React.PropTypes.string
    },

    getDefaultProps() {
        return {
            separator: ':',
            labelClassName: 'col-xs-5 col-sm-4 col-md-3 col-lg-3',
            valueClassName: 'col-xs-7 col-sm-8 col-md-9 col-lg-9'
        };
    },

    render() {
        let value = this.props.value;
        if (this.props.children){
            value = (
                <div className="row-same-height">
                    <div className="col-xs-6 col-xs-height col-bottom no-padding">
                        { this.props.value }
                    </div>
                    <div className="col-xs-6 col-xs-height">
                        { this.props.children }
                    </div>
                </div>);
        }
        return (
            <div className="row ascribe-detail-property">
                <div className="row-same-height">
                    <div className={this.props.labelClassName + ' col-xs-height col-bottom'}>
                        <div>{ this.props.label + this.props.separator}</div>
                    </div>
                    <div className={this.props.valueClassName + ' col-xs-height col-bottom'}>
                        {value}
                    </div>
                </div>
            </div>
        );
    }
});

let EditionDetailHistoryIterator = React.createClass({
    propTypes: {
        history: React.PropTypes.array
    },

    render() {
        return (
            <Form>
                {this.props.history.map((historicalEvent, i) => {
                    return (
                        <Property
                                name={i}
                                key={i}
                                label={ historicalEvent[0] }
                                editable={false}>
                            <pre className="ascribe-pre">{ historicalEvent[1] }</pre>
                        </Property>
                    );
                })}
                <hr />
            </Form>
        );
    }
});

let EditionPersonalNote = React.createClass({
    propTypes: {
        edition: React.PropTypes.object,
        currentUser: React.PropTypes.object,
        handleSuccess: React.PropTypes.func
    },
    showNotification(){
        this.props.handleSuccess();
        let notification = new GlobalNotificationModel('Private note saved', 'success');
        GlobalNotificationActions.appendGlobalNotification(notification);
    },

    render() {
        if (this.props.currentUser.username && true || false) {
            return (
                <Form
                    url={apiUrls.note_notes}
                    handleSuccess={this.showNotification}>
                    <Property
                        name='note'
                        label='Personal note (private)'
                        editable={true}>
                        <InputTextAreaToggable
                            rows={3}
                            editable={true}
                            defaultValue={this.props.edition.note_from_user}
                            placeholder='Enter a personal note...'
                            required/>
                    </Property>
                    <Property hidden={true} name='bitcoin_id'>
                        <input defaultValue={this.props.edition.bitcoin_id}/>
                    </Property>
                    <hr />
                </Form>
            );
        }
        return null;
    }
});

let EditionPublicEditionNote = React.createClass({
    propTypes: {
        edition: React.PropTypes.object,
        handleSuccess: React.PropTypes.func
    },
    showNotification(){
        this.props.handleSuccess();
        let notification = new GlobalNotificationModel('Public note saved', 'success');
        GlobalNotificationActions.appendGlobalNotification(notification);
    },
    render() {
        let isEditable = this.props.edition.acl.indexOf('edit') > -1;
        if (this.props.edition.acl.indexOf('edit') > -1 || this.props.edition.public_note){
            return (
                <Form
                    url={apiUrls.note_edition}
                    handleSuccess={this.showNotification}>
                    <Property
                        name='note'
                        label='Edition note (public)'
                        editable={isEditable}>
                        <InputTextAreaToggable
                            rows={3}
                            editable={isEditable}
                            defaultValue={this.props.edition.public_note}
                            placeholder='Enter a public note for this edition...'
                            required/>
                    </Property>
                    <Property hidden={true} name='bitcoin_id'>
                        <input defaultValue={this.props.edition.bitcoin_id}/>
                    </Property>
                    <hr />
                </Form>
            );
        }
        return null;
    }
});


let EditionFurtherDetails = React.createClass({
    propTypes: {
        edition: React.PropTypes.object,
        handleSuccess: React.PropTypes.func
    },

    getInitialState() {
        return {
            loading: false
        };
    },

    showNotification(){
        this.props.handleSuccess();
        let notification = new GlobalNotificationModel('Details updated', 'success');
        GlobalNotificationActions.appendGlobalNotification(notification);
    },

    submitKey(key){
        this.setState({
            otherDataKey: key
        });
    },

    setIsUploadReady(isReady) {
        this.setState({
            isUploadReady: isReady
        });
    },

    isReadyForFormSubmission(files) {
        files = files.filter((file) => file.status !== 'deleted' && file.status !== 'canceled');
        if(files.length > 0 && files[0].status === 'upload successful') {
            return true;
        } else {
            return false;
        }
    },

    render() {
        let editable = this.props.edition.acl.indexOf('edit') > -1;

        return (
            <Row>
                <Col md={12} className="ascribe-edition-personal-note">
                    <PieceExtraDataForm
                        name='artist_contact_info'
                        title='Artist Contact Info'
                        handleSuccess={this.showNotification}
                        editable={editable}
                        edition={this.props.edition} />
                    <PieceExtraDataForm
                        name='display_instructions'
                        title='Display Instructions'
                        handleSuccess={this.showNotification}
                        editable={editable}
                        edition={this.props.edition} />
                    <PieceExtraDataForm
                        name='technology_details'
                        title='Technology Details'
                        handleSuccess={this.showNotification}
                        editable={editable}
                        edition={this.props.edition} />
                    <FileUploader
                        submitKey={this.submitKey}
                        setIsUploadReady={this.setIsUploadReady}
                        isReadyForFormSubmission={this.isReadyForFormSubmission}
                        editable={editable}
                        edition={this.props.edition}/>
                </Col>
            </Row>
        );
    }
});

let FileUploader = React.createClass({
    propTypes: {
        edition: React.PropTypes.object,
        setIsUploadReady: React.PropTypes.func,
        submitKey: React.PropTypes.func,
        isReadyForFormSubmission: React.PropTypes.func,
        editable: React.PropTypes.bool
    },

    render() {
        // Essentially there a three cases important to the fileuploader
        //
        // 1. there is no other_data => do not show the fileuploader at all
        // 2. there is other_data, but user has no edit rights => show fileuploader but without action buttons
        // 3. both other_data and editable are defined or true => show fileuploade with all action buttons
        if (!this.props.editable && !this.props.edition.other_data){
            return null;
        }
        return (
            <Form>
                <Property
                    label="Additional files">
                    <ReactS3FineUploader
                        keyRoutine={{
                            url: AppConstants.serverUrl + 's3/key/',
                            fileClass: 'otherdata',
                            bitcoinId: this.props.edition.bitcoin_id
                        }}
                        createBlobRoutine={{
                            url: apiUrls.blob_otherdatas,
                            bitcoinId: this.props.edition.bitcoin_id
                        }}
                        validation={{
                            itemLimit: 100000,
                            sizeLimit: '10000000'
                        }}
                        submitKey={this.props.submitKey}
                        setIsUploadReady={this.props.setIsUploadReady}
                        isReadyForFormSubmission={this.props.isReadyForFormSubmission}
                        session={{
                            endpoint: AppConstants.serverUrl + 'api/blob/otherdatas/fineuploader_session/',
                            customHeaders: {
                                'X-CSRFToken': getCookie('csrftoken')
                            },
                            params: {
                                'pk': this.props.edition.other_data ? this.props.edition.other_data.id : null
                            }
                        }}
                        areAssetsDownloadable={true}
                        areAssetsEditable={this.props.editable}/>
                </Property>
                <hr />
            </Form>
        );
    }
});

let CoaDetails = React.createClass({
    propTypes: {
        edition: React.PropTypes.object
    },

    getInitialState() {
        return CoaStore.getState();
    },

    componentDidMount() {
        CoaStore.listen(this.onChange);
        if (this.props.edition.coa) {
            CoaActions.fetchOne(this.props.edition.coa);
        }
        else{
            console.log('create coa');
            CoaActions.create(this.props.edition);
        }
    },

    componentWillUnmount() {
        CoaStore.unlisten(this.onChange);
    },

    onChange(state) {
        this.setState(state);
    },

    render() {
        if (this.state.coa.url_safe) {
            return (
                <div>
                    <p className="text-center ascribe-button-list">
                        <button className="btn btn-default btn-xs" href={this.state.coa.url_safe} target="_blank">
                            Download <Glyphicon glyph="cloud-download"/>
                        </button>
                        <Link to="coa_verify">
                            <button className="btn btn-default btn-xs">
                                Verify <Glyphicon glyph="check"/>
                            </button>
                        </Link>

                    </p>
                </div>
            );
        }
        return (
            <div className="text-center">
                <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
            </div>);

    }
});

export default Edition;