
/*
 * 
 *   Copyright 2016 RIFT.IO Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
import React from 'react';
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
import RecordViewStore from '../recordViewer/recordViewStore.js';
import Button from 'widgets/button/rw.button.js';
import './nsConfigPrimitives.scss';
import TextInput from 'widgets/form_controls/textInput.jsx';
import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';

class NsrConfigPrimitives extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
        this.state.vnfrMap = null;
        this.state.nsConfigPrimitives = null;
    }

    componentWillReceiveProps(props) {
        let vnfrs = props.data['vnfrs'];
        let vnfrMap = {};
        let nsConfigPrimitives = [];
        let vnfList = [];
        if (vnfrs &&  !this.state.nsConfigPrimitives) {
            vnfrs.map((vnfr) => {
                let vnfrConfigPrimitive = {};
                vnfrConfigPrimitive.name = vnfr['short-name'];
                vnfrConfigPrimitive['vnfr-id-ref'] = vnfr['id'];
                //input references
                let configPrimitives = vnfr['vnf-configuration'] && vnfr['vnf-configuration']['service-primitive'];
                //input references by key
                let vnfrConfigPrimitives = {}

                if (configPrimitives) {
                    let vnfPrimitiveList = [];
                    configPrimitives.map((configPrimitive) => {
                        vnfrConfigPrimitives[configPrimitive.name] = configPrimitive;
                        vnfPrimitiveList.push({
                            name: configPrimitive.name,
                            parameter: configPrimitive.parameter
                        })
                    });
                    vnfrConfigPrimitive['service-primitives'] = vnfrConfigPrimitives;
                    vnfrMap[vnfr['member-vnf-index-ref']] = vnfrConfigPrimitive;
                }
            });
            //nsr service-primitives
            props.data['service-primitive'] && props.data['service-primitive'].map((nsConfigPrimitive, nsConfigPrimitiveIndex) => {
                 //Add optional field to group. Necessary for driving state.
                let optionalizedNsConfigPrimitiveGroup = nsConfigPrimitive['parameter-group'] && nsConfigPrimitive['parameter-group'].map((parameterGroup)=>{
                    if(parameterGroup && parameterGroup.mandatory != "true") {
                        parameterGroup.optionalChecked = true;
                    };
                    return parameterGroup;
                });
                let nscp = {
                    name: nsConfigPrimitive.name,
                    'nsr_id_ref': props.data.id,
                    'parameter': nsConfigPrimitive.parameter,
                    'parameter-group': optionalizedNsConfigPrimitiveGroup,
                    'vnf-primitive-group':[]
                }

                nsConfigPrimitive['vnf-primitive-group'] && nsConfigPrimitive['vnf-primitive-group'].map((vnfPrimitiveGroup, vnfPrimitiveGroupIndex) => {
                    let vnfMap = vnfrMap[vnfPrimitiveGroup['member-vnf-index-ref']];
                    let vnfGroup = {};
                    vnfGroup.name = vnfMap.name;
                    vnfGroup['member-vnf-index-ref'] = vnfPrimitiveGroup['member-vnf-index-ref'];
                    vnfGroup['vnfr-id-ref'] = vnfMap['vnfr-id-ref'];
                    vnfGroup.inputs = [];
                    vnfPrimitiveGroup.primitive.map((primitive, primitiveIndex) => {
                        console.log(primitive);
                        primitive.index = primitiveIndex;
                        primitive.parameter = [];
                        vnfMap['service-primitives'][primitive.name].parameter.map(function(p) {
                            p.index = primitiveIndex;
                            let paramCopy = p;
                            paramCopy.value = undefined;
                            primitive.parameter.push(paramCopy);
                        });
                        vnfGroup.inputs.push(primitive);
                    });
                    nscp['vnf-primitive-group'].push(vnfGroup);
                });
                nsConfigPrimitives.push(nscp);
            });
            this.setState({
                vnfrMap: vnfrMap,
                data: props.data,
                nsConfigPrimitives: nsConfigPrimitives
            });
        }
    }

    handleParamChange = (parameterIndex, vnfPrimitiveIndex, vnfListIndex, nsConfigPrimitiveIndex, event) => {
        let nsConfigPrimitives = this.state.nsConfigPrimitives;
        nsConfigPrimitives[nsConfigPrimitiveIndex]['vnf-primitive-group'][vnfListIndex]['inputs'][vnfPrimitiveIndex]['parameter'][parameterIndex]['value'] = event.target.value;
        this.setState({
            nsConfigPrimitives: nsConfigPrimitives
        });
    }

    handleNsParamChange = (parameterIndex, nsConfigPrimitiveIndex, event) => {
        let nsConfigPrimitives = this.state.nsConfigPrimitives;
        nsConfigPrimitives[nsConfigPrimitiveIndex]['parameter'][parameterIndex]['value'] = event.target.value;
        this.setState({
            nsConfigPrimitives: nsConfigPrimitives
        });
    }

    handleNsParamGroupParamChange = (parameterIndex, parameterGroupIndex, nsConfigPrimitiveIndex, event) => {
        let nsConfigPrimitives = this.state.nsConfigPrimitives;
        nsConfigPrimitives[nsConfigPrimitiveIndex]['parameter-group'][parameterGroupIndex]['parameter'][parameterIndex]['value'] = event.target.value;
        this.setState({
            nsConfigPrimitives: nsConfigPrimitives
        });
    }

    handleExecuteClick = (nsConfigPrimitiveIndex, event) => {
        var isValid = RecordViewStore.validateInputs({
            nsConfigPrimitives: this.state.nsConfigPrimitives,
            nsConfigPrimitiveIndex: nsConfigPrimitiveIndex
        });
        if(isValid) {
            RecordViewStore.constructAndTriggerNsConfigPrimitive({
                nsConfigPrimitives: this.state.nsConfigPrimitives,
                nsConfigPrimitiveIndex: nsConfigPrimitiveIndex
             });
            //Need a better way to reset
            //Reset disabled per TEF request
            // this.setState({
            //     nsConfigPrimitives: null
            // })
        } else {
                this.props.actions.showNotification('Could not execute service config. Please review your parameters');
        }
    }
    handleOptionalCheck = (parameterGroupIndex, nsConfigPrimitiveIndex, event) => {
        let nsConfigPrimitives = this.state.nsConfigPrimitives;
        let optionalChecked = nsConfigPrimitives[nsConfigPrimitiveIndex]['parameter-group'][parameterGroupIndex].optionalChecked;
        nsConfigPrimitives[nsConfigPrimitiveIndex]['parameter-group'][parameterGroupIndex].optionalChecked = !optionalChecked;
        console.log(nsConfigPrimitives)
        this.setState({
            nsConfigPrimitives: nsConfigPrimitives
        });
    }
    constructConfigPrimitiveTabs = (tabList, tabPanels) => {
        let self = this;
        let defaultFromRpc = '';
        //coded here for dev purposes
        let mandatoryFieldValue = 'true';
        if (self.state.vnfrMap) {
            this.state.nsConfigPrimitives && this.state.nsConfigPrimitives.map((nsConfigPrimitive, nsConfigPrimitiveIndex) => {
                tabList.push(
                    <Tab key={nsConfigPrimitiveIndex}>{nsConfigPrimitive.name}</Tab>
                );
                tabPanels.push(
                    (
                        <TabPanel key={nsConfigPrimitiveIndex + '-panel'}>
                            <h4>{nsConfigPrimitive.name}</h4>
                            <div className="noticeSubText noticeSubText_right">
                                * required
                            </div>
                            {nsConfigPrimitive['parameter'] && nsConfigPrimitive['parameter'].map((parameter, parameterIndex) => {
                                let optionalField = '';
                                let displayField = '';
								let defaultValue = parameter['default-value'] || '';
                                let isFieldHidden = (parameter['hidden'] && parameter['hidden'] == 'true') || false;
                                let isFieldReadOnly = (parameter['read-only'] && parameter['read-only'] == 'true') || false;
                                if (parameter.mandatory == mandatoryFieldValue) {
                                    optionalField = <span className="required">*</span>
                                }
                                if (isFieldReadOnly) {
                                    displayField = (
                                        <label data-required={(parameter.mandatory == mandatoryFieldValue)}>
                                            {parameter.name}
                                            <div className='readonly'>
                                                {parameter.value || defaultValue}
                                            </div>
                                        </label>
                                    )
                                } else {
                                    displayField = <TextInput label={parameter.name} required={(parameter.mandatory == mandatoryFieldValue)} className="" type="text" defaultValue={defaultValue} value={parameter.value} onChange={this.handleNsParamChange.bind(this, parameterIndex, nsConfigPrimitiveIndex)} />;
                                }
                                return (
                                    <div key={parameterIndex} className="nsConfigPrimitiveParameters" style={{display: isFieldHidden ? 'none':'inherit'}}>
                                        <ul>
                                        {
                                            <li key={parameterIndex} className="">
                                                    {displayField}
                                            </li>
                                        }
                                        </ul>
                                    </div>
                                )
                            })}
                            {nsConfigPrimitive['parameter-group'] && nsConfigPrimitive['parameter-group'].map((parameterGroup, parameterGroupIndex) => {
                                let optionalField = '';
                                let overlayGroup = null;
                                let isOptionalGroup = parameterGroup.mandatory != mandatoryFieldValue;
                                let optionalChecked = parameterGroup.optionalChecked;
                                let inputIsDiabled = (!optionalChecked && isOptionalGroup);
                                if (isOptionalGroup) {
                                    optionalField = <input type="checkbox" name="" checked={optionalChecked} onChange={self.handleOptionalCheck.bind(null, parameterGroupIndex, nsConfigPrimitiveIndex)} />;
                                    // overlayGroup = <div className="configGroupOverlay"></div>
                                }
                                return (
                                    <div key={parameterGroupIndex} className="nsConfigPrimitiveParameterGroupParameters">
                                    <h2>{parameterGroup.name} {optionalField}</h2>
                                    <div className="parameterGroup">
                                        {overlayGroup}
                                        <ul className="">
                                                <li className="">

                                                    {parameterGroup['parameter'] && parameterGroup['parameter'].map((parameter, parameterIndex) => {
                                                        let optionalField = '';
                                                        let displayField = '';
                                                        let defaultValue = parameter['default-value'] || '';
                                                        let isFieldHidden = (parameter['hidden'] && parameter['hidden'] == 'true') || false;
                                                        let isFieldReadOnly = (parameter['read-only'] && parameter['read-only'] == 'true') || false;
                                                        if (parameter.mandatory == mandatoryFieldValue) {
                                                            optionalField = <span className="required">*</span>
                                                        }
                                                        if (isFieldReadOnly) {
                                                            displayField = <div className='readonly'>{parameter.value || defaultValue}</div>
                                                        } else {
                                                            displayField = <input required={(parameter.mandatory == mandatoryFieldValue)} className="" disabled={inputIsDiabled} type="text" defaultValue={defaultValue} value={parameter.value} onChange={this.handleNsParamGroupParamChange.bind(this, parameterIndex, parameterGroupIndex, nsConfigPrimitiveIndex)} />
                                                        }
                                                        if (parameter.mandatory == mandatoryFieldValue) {
                                                            optionalField = <span className="required">*</span>
                                                        }
                                                        return (
                                                            <div key={parameterIndex} className="nsConfigPrimitiveParameters" style={{display: isFieldHidden ? 'none':'inherit'}}>
                                                                <ul>
                                                                {
                                                                    <li key={parameterIndex} className="">
                                                                        <label className={inputIsDiabled && 'disabled'} data-required={(parameter.mandatory == mandatoryFieldValue)}>
                                                                            {parameter.name}
                                                                            {displayField}
                                                                        </label>

                                                                    </li>
                                                                }
                                                                </ul>
                                                            </div>
                                                        )
                                                    })}
                                                </li>
                                            </ul>
                                        </div>
                                    </div>
                                );
                            })}
                            {nsConfigPrimitive['vnf-primitive-group'] && nsConfigPrimitive['vnf-primitive-group'].map((vnfGroup, vnfGroupIndex) => {
                                return (
                                    <div key={vnfGroupIndex} className="vnfParamGroup">
                                        <h2>{vnfGroup.name}</h2>

                                            {vnfGroup.inputs.map((inputGroup, inputGroupIndex) => {
                                                return (
                                                    <div key={inputGroupIndex}>
                                                        <h3>{inputGroup.name}</h3>
                                                        <ul className="parameterGroup">
                                                        {
                                                            inputGroup.parameter.map((input, inputIndex) => {
                                                                let optionalField = '';
                                                                let displayField = '';
																let defaultValue = input['default-value'] || '';
                                                                let isFieldHidden = (input['hidden'] && input['hidden'] == 'true') || false;
                                                                let isFieldReadOnly = (input['read-only'] && input['read-only'] == 'true') || false;
                                                                if (input.mandatory == mandatoryFieldValue) {
                                                                    optionalField = <span className="required">*</span>
                                                                }
                                                                if (isFieldReadOnly) {
                                                                    displayField = <div className='readonly'>{input.value || defaultValue}</div>
                                                                } else {
                                                                    displayField = <TextInput label={input.name} type="text" required={(input.mandatory == mandatoryFieldValue)} className="" type="text" defaultValue={defaultValue} value={input.value} onChange={this.handleParamChange.bind(this, inputIndex, inputGroupIndex, vnfGroupIndex, nsConfigPrimitiveIndex)}/>
                                                                }
                                                                return (
                                                                    <li key={inputIndex} style={{display: isFieldHidden ? 'none':'inherit'}}>
                                                                        {displayField}
                                                                    </li>
                                                                )
                                                            })
                                                        }
                                                        </ul>
                                                    </div>
                                                )
                                            })}

                                    </div>
                                )
                            })}
                            <Button label="Submit" isLoading={this.state.isSaving} onClick={this.handleExecuteClick.bind(this, nsConfigPrimitiveIndex)} className="dark"/>
                        </TabPanel>
                    )
                );
            });
        }
    }

    handleSelect = (index, last) => {
        // console.log('Selected tab is', index, 'last index is', last);
    }
    render() {

        let tabList = [];
        let tabPanels = [];
        let isConfiguring = (this.props.data['config-status'] && this.props.data['config-status'] != 'configured') || false;
        let displayConfigStatus = isConfiguring ? '(Disabled - Configuring)': '';

        this.constructConfigPrimitiveTabs(tabList, tabPanels);

        return (
            <div className="nsConfigPrimitives">
                <div className="launchpadCard_title">
                  SERVICE-PRIMITIVES {displayConfigStatus}
                </div>
                <div className={isConfiguring ? 'configuring': '' + 'nsConfigPrimitiveTabs'}>
                    <Tabs onSelect={this.handleSelect}>
                        <TabList>
                            {tabList}
                        </TabList>
                        {tabPanels}
                    </Tabs>
                </div>
            </div>

        );
    }
}


function deepCopy (toCopy, copyObj) {
    for (let k in toCopy) {
        switch (toCopy[k].constructor.name) {
            case "String":
                copyObj[k] = toCopy[k];
                break;
            case "Array":
                copyObj[k] = [];
                toCopy[k].map((v) => {
                    copyObj[k].push(v)
                });
                break;
            case "Object":
                deepCopy(toCopy[k], copyObj[k]);
                break;
            default:
                copyObj[k] = toCopy[k]
        }
    }
    return copyObj;
}
export default SkyquakeComponent(NsrConfigPrimitives);
