// redux dependencies
import { connect } from 'react-redux'
import createReducer from 'lib/reducer';
import backendRequest from 'lib/backend';

// react component dependencies
import React, { Component } from 'react'
import { defineMessages, injectIntl, FormattedDate } from 'react-intl';

import messages from './messages';



/* REDUX */
const initialState = {};
const emptyList = {
    status: null,
    data: []
};

let _reducer = createReducer(initialState);

function registerComponent(unitId, templateId) {
    return {
        type: '@@templates/REGISTER',
        payload: templateId,
        meta: {
            unitId,
            templateId
        }
    }
}


function unregisterComponent(unitId, templateId) {
    return {
        type: '@@templates/UNREGISTER',
        payload: templateId,
        meta: {
            unitId,
            templateId
        }
    }
}


function fetchTemplates(unitId, templateId) {
    return {
        type: '@@templates/FETCH',
        payload: backendRequest(`/api/${unitId}/templates/${templateId}`),
        meta: {
            key: templateId,
            unitId,
            templateId
        }
    }
}



_reducer.handleAction("@@templates/REGISTER", (state, action) => state.updateIn([action.payload, "count"], val => isNaN(val) ? 1 : val + 1 ));
_reducer.handleAction("@@templates/UNREGISTER", (state, action) => {
    let count = state.getIn([action.payload, "count"], 0);
    if (count < 2) {
        state = state.remove(action.payload);
    } else {
        state = state.updateIn([action.payload, "count"], val => val - 1);
    }
    return state;
} );



_reducer.handleAction("@@templates/FETCH_PENDING", (state, action) => state.setIn([action.meta.key, "list", "status"], "pending") );
_reducer.handleAction("@@templates/FETCH_FULFILLED", (state, action) => state.setIn([action.meta.key, "list", "status"], "success").setIn([action.meta.key, "list", "data"], action.payload.body) );
_reducer.handleAction("@@templates/FETCH_REJECTED", (state, action) => state.setIn([action.meta.key, "list", "status"], "failure").deleteIn([action.meta.key, "list", "data"]) );



//export reducer
export const reducer = _reducer.export();


/* ******************************************* */
/* UI Components                               */
/* ******************************************* */

require("./template.scss")





class Templates extends Component {

    constructor(props) {
        super(props);

        this.onDrop = this.onDrop.bind(this);
        this.renderRow = this.renderRow.bind(this);
        this.deleteRow = this.deleteRow.bind(this);
        this.renameRow = this.renameRow.bind(this);

        this.state = { modal: null };
    }


    async onDrop(acceptedFiles, rejectedFiles) {
        const { unitId, objectType, templateId, disabled } = this.props;

        if (disabled) {
            //TODO warn the user
            return;
        }

        for (let i = 0; i < acceptedFiles.length; i++) {
            await upload(`/api/${unitId}/templates/${objectType}/${templateId}`, acceptedFiles[i]);
            //await this.props.uploadTemplate(unitId, objectType, templateId, acceptedFiles[i]);
        }

        await this.props.fetchData();
    }


    async deleteRow(id) {
        await this.props.deleteTemplate(id);
        await this.props.fetchData();
    }


    async renameRow(item, name) {
        try {
            await this.props.renameTemplate(item.id, name);
            this.setState({ modal: null, item: null });
        } catch (e) {
            console.error(e);
        }
        await this.props.fetchData();
    }

    componentWillReceiveProps(props) {
        //clearInfoMessages(this);
        if (props.templateId != this.props.templateId) {
            this.props.fetchData();
        }
    }


    //TODO ensure data
    componentWillMount() {
        this.props.registerComponent();

        //refresh list?
        const { status } = this.props;
        if (status !== "pending" && this.props.templateId) {
            this.props.fetchData();
        }
    }
    

    componentWillUnmount() {
        this.props.unregisterComponent();
    }
    

    renderRow(item, idx) {
        const { unitId, objectType, templateId, disabled } = this.props;
        return (
            <div key={idx} className="list-row bottom-border">
                <div className="row-content">
                    <div className="float-left left p10-5">
                        <div className="main">
                            { item.name }
                        </div>
                        <div className="secondary">
                            { item.mimeType }
                        </div>
                    </div>
                </div>
                <div className="row-menu">
                    <button 
                        className="icon" 
                        type="button" 
                        onClick={ (e) => this.setState({ modal: item.name, item: item }) }>
                        
                    </button>
                    <button 
                        className="icon" 
                        type="button" 
                        onClick={ (e) => download('/api/' + unitId + '/templates/' + objectType + '/' + templateId + '/' + item.id) }>
                        
                    </button>  
                    <button 
                        className="icon" 
                        type="button" 
                        onClick={ (e) => this.deleteRow(item.id) }>
                        
                    </button>
                </div>
            </div>
        );
    }

    render() {
        let { 
            intl, 
            status, 
            error, 
            data,
            showList = true, 
            showDropzone = true,
            editable = true,
            disabled,
            unitId, 
            objectType, 
            templateId, 
            icon = ""
        } = this.props;

        
        return (
            <div className={`templates ${this.props.className||""} ${ disabled ? "disabled" : ""}`}>
                <h3>
                    <i className="icon">{ icon }</i> { intl.formatMessage(messages.title) }
                </h3>

                <Dropzone onDrop={this.onDrop} className="dropzone" disabled={ disabled }>
                    <i className="icon"></i>{ intl.formatMessage(messages.hint) }
                </Dropzone>

                { showList ? (
                <div className="row-margin-10">
                    <div className="row">
                        { data && data.length ? data.map(this.renderRow) : null }
                    </div>
                </div>
                ) : null }

            </div>
            );
    }
}


const mapStateToProps = (state, props) => {
    let s = state.getIn(["template", templateKey(props.objectType, props.templateId), "list"]);
    if (!s) {
        return emptyList;
    }
    return s.toJS();
}



function mapDispatchToProps(dispatch, props) {
    return {
        registerComponent: () => dispatch(registerComponent(props.unitId, props.objectType, props.templateId)),
        unregisterComponent: () => dispatch(unregisterComponent(props.unitId, props.objectType, props.templateId)),
        fetchData: () => dispatch(fetchTemplates(props.unitId, props.objectType, props.templateId)),
        deleteTemplate: (templateId) => dispatch(deleteTemplate(props.unitId, props.objectType, props.templateId, templateId)),
        renameTemplate: (templateId, name) => dispatch(renameTemplate(props.unitId, props.objectType, props.templateId, templateId, name))
    };
}


Templates = connect(mapStateToProps, mapDispatchToProps)(Templates);

export default injectIntl(Templates);

